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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]
### Added
- `DateTimeFromStringDecoder` now supports strict mode configuration to enforce strict date parsing (default: true). In strict mode, invalid dates like "2025-04-31" will be rejected instead of being automatically adjusted.

### Removed
- Support for PHP < 7.4
- `Codec` and `Encoder` interfaces. Removed `Codecs` entrypoint.
Expand Down
8 changes: 4 additions & 4 deletions src/Decoder.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,21 @@
interface Decoder
{
/**
* @param mixed $i
*
* @psalm-param I $i
* @psalm-param Context $context
*
* @psalm-return Validation<A>
*
* @param mixed $i
*/
public function validate($i, Context $context): Validation;

/**
* @param mixed $i
*
* @psalm-param I $i
*
* @psalm-return Validation<A>
*
* @param mixed $i
*/
public function decode($i): Validation;

Expand Down
20 changes: 10 additions & 10 deletions src/Decoders.php
Original file line number Diff line number Diff line change
Expand Up @@ -200,11 +200,11 @@ public static function transformValidationSuccess(callable $f, Decoder $da): Dec
/**
* @psalm-template T of bool | string | int
*
* @param mixed $l
*
* @psalm-param T $l
*
* @psalm-return Decoder<mixed, T>
*
* @param mixed $l
*/
public static function literal($l): Decoder
{
Expand All @@ -227,16 +227,16 @@ public static function listOf(Decoder $elementDecoder): Decoder
/**
* @psalm-template MapOfDecoders of non-empty-array<array-key, Decoder<mixed, mixed>>
*
* @psalm-param MapOfDecoders $props
*
* @psalm-return Decoder<mixed, non-empty-array<array-key, mixed>>
*
* @param Decoder[] $props
*
* @psalm-param MapOfDecoders $props
*
* @return Decoder
*
* Waiting for this feature to provide a better typing. I need something like mapped types from Typescript.
*
* @psalm-return Decoder<mixed, non-empty-array<array-key, mixed>>
*
* @see https://github.com/vimeo/psalm/issues/3589
*/
public static function arrayProps(array $props): Decoder
Expand Down Expand Up @@ -281,11 +281,11 @@ public static function classFromArrayPropsDecoder(
/**
* @psalm-template U
*
* @param null|mixed $default
*
* @psalm-param U $default
*
* @psalm-return Decoder<mixed, U>
*
* @param null|mixed $default
*/
public static function undefined($default = null): Decoder
{
Expand Down Expand Up @@ -365,9 +365,9 @@ public static function intFromString(): Decoder
/**
* @psalm-return Decoder<string, \DateTimeInterface>
*/
public static function dateTimeFromString(string $format = \DATE_ATOM): Decoder
public static function dateTimeFromString(string $format = \DATE_ATOM, bool $strict = true): Decoder
{
return new DateTimeFromStringDecoder($format);
return new DateTimeFromStringDecoder($format, $strict);
}

/**
Expand Down
8 changes: 4 additions & 4 deletions src/Internal/Combinators/ComposeDecoder.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,20 +38,20 @@ public function __construct(
}

/**
* @param mixed $i
*
* @psalm-param IA $i
* @psalm-param Context $context
*
* @psalm-return Validation<B>
*
* @param mixed $i
*/
public function validate($i, Context $context): Validation
{
return Validation::bind(
/**
* @psalm-param A $aValue
*
* @param mixed $aValue
*
* @psalm-param A $aValue
*/
fn($aValue): Validation => $this->db->validate($aValue, $context),
$this->da->validate($i, $context)
Expand Down
10 changes: 5 additions & 5 deletions src/Internal/Combinators/IntersectionDecoder.php
Original file line number Diff line number Diff line change
Expand Up @@ -92,15 +92,15 @@ public function getName(): string
* @template T1
* @template T2
*
* @psalm-param T1 $a
* @psalm-param T2 $b
*
* @psalm-return T1&T2
*
* @param mixed $a
* @param mixed $b
*
* @psalm-param T1 $a
* @psalm-param T2 $b
*
* @return array|object
*
* @psalm-return T1&T2
*/
private static function intersectResults($a, $b)
{
Expand Down
8 changes: 4 additions & 4 deletions src/Internal/Combinators/LiteralDecoder.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ final class LiteralDecoder implements Decoder
private $literal;

/**
* @psalm-param T $literal
*
* @param mixed $literal
*
* @psalm-param T $literal
*/
public function __construct($literal)
{
Expand All @@ -58,9 +58,9 @@ public function getName(): string
}

/**
* @psalm-param literable $x
*
* @param mixed $x
*
* @psalm-param literable $x
*/
private static function literalName($x): string
{
Expand Down
8 changes: 4 additions & 4 deletions src/Internal/FunctionUtils.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
final class FunctionUtils
{
/**
* @psalm-param non-empty-array<array-key, Decoder> $props
*
* @param Decoder[] $props
*
* @psalm-param non-empty-array<array-key, Decoder> $props
*/
public static function nameFromProps(array $props): string
{
Expand All @@ -39,12 +39,12 @@ public static function nameFromProps(array $props): string
* @psalm-template A
* @psalm-template I
*
* @param mixed $input
*
* @psalm-param Decoder<I, A> $decoder
* @psalm-param I $input
*
* @psalm-return Validation<A>
*
* @param mixed $input
*/
public static function standardDecode(Decoder $decoder, $input): Validation
{
Expand Down
4 changes: 2 additions & 2 deletions src/Internal/Primitives/UndefinedDecoder.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ final class UndefinedDecoder implements Decoder
private $default;

/**
* @psalm-param U $default
*
* @param mixed $default
*
* @psalm-param U $default
*/
public function __construct($default)
{
Expand Down
16 changes: 15 additions & 1 deletion src/Internal/Useful/DateTimeFromStringDecoder.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,15 @@ final class DateTimeFromStringDecoder implements Decoder
*/
private string $format;

public function __construct(string $format = \DATE_ATOM)
/**
* @psalm-readonly
*/
private bool $strict;

public function __construct(string $format = \DATE_ATOM, bool $strict = true)
{
$this->format = $format;
$this->strict = $strict;
}

public function validate($i, Context $context): Validation
Expand All @@ -39,6 +45,14 @@ public function validate($i, Context $context): Validation
return Validation::failure($i, $context);
}

// In strict mode, check if there were any parsing errors or warnings
if ($this->strict) {
$errors = \DateTime::getLastErrors();
if ($errors !== false && ($errors['error_count'] > 0 || $errors['warning_count'] > 0)) {
return Validation::failure($i, $context);
}
}

/** @var \DateTimeInterface $r */
return Validation::success($r);
}
Expand Down
4 changes: 2 additions & 2 deletions src/Validation/ContextEntry.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ final class ContextEntry
private $actual;

/**
* @param mixed $actual
*
* @psalm-param string $key
* @psalm-param Decoder<mixed, mixed> $decoder
* @psalm-param mixed $actual
*
* @param mixed $actual
*/
public function __construct(
string $key,
Expand Down
4 changes: 2 additions & 2 deletions src/Validation/ListOfValidation.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,9 @@ function (array $es) use (&$errors): void {
$errors[] = $es;
},
/**
* @psalm-param Values $x
*
* @param mixed $x
*
* @psalm-param Values $x
*/
function ($x) use ($k, &$results): void {
/** @var K $k */
Expand Down
4 changes: 2 additions & 2 deletions src/Validation/VError.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ final class VError
private ?string $message = null;

/**
* @param mixed $value
*
* @psalm-param mixed $value
* @psalm-param Context $context
* @psalm-param string|null $message
*
* @param mixed $value
*/
public function __construct(
$value,
Expand Down
12 changes: 6 additions & 6 deletions src/Validation/Validation.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ abstract class Validation
/**
* @psalm-template T
*
* @param mixed $a
*
* @psalm-param T $a
*
* @psalm-return ValidationSuccess<T>
*
* @param mixed $a
*/
public static function success($a): self
{
Expand All @@ -26,11 +26,11 @@ public static function success($a): self
/**
* @psalm-template T
*
* @param VError[] $errors
*
* @psalm-param list<VError> $errors
*
* @psalm-return ValidationFailures<T>
*
* @param VError[] $errors
*/
public static function failures(array $errors): self
{
Expand All @@ -40,13 +40,13 @@ public static function failures(array $errors): self
/**
* @psalm-template T
*
* @param mixed $value
*
* @psalm-param mixed $value
* @psalm-param Context $context
* @psalm-param string|null $message
*
* @psalm-return ValidationFailures<T>
*
* @param mixed $value
*/
public static function failure($value, Context $context, ?string $message = null): self
{
Expand Down
8 changes: 4 additions & 4 deletions src/Validation/ValidationFailures.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,19 @@ final class ValidationFailures extends Validation
private array $errors;

/**
* @psalm-param list<VError> $errors
*
* @param VError[] $errors
*
* @psalm-param list<VError> $errors
*/
public function __construct(array $errors)
{
$this->errors = $errors;
}

/**
* @psalm-return list<VError>
*
* @return VError[]
*
* @psalm-return list<VError>
*/
public function getErrors(): array
{
Expand Down
4 changes: 2 additions & 2 deletions src/Validation/ValidationSuccess.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ final class ValidationSuccess extends Validation
private $value;

/**
* @psalm-param A $a
*
* @param mixed $a
*
* @psalm-param A $a
*/
public function __construct($a)
{
Expand Down
Loading