cline/option

There is no license information available for the latest version (1.1.0) of this package.

1.1.0 2025-10-03 04:59 UTC

This package is auto-updated.

Last update: 2025-10-03 05:00:24 UTC


README

This directory contains a Rust-aligned Option implementation with a small Result interop. It provides expressive, null-safe code paths and ergonomic controller helpers for Laravel.

Highlights

  • Null-safety with Option::fromNullable($v) and Option::fromValue($v, $noneValue)
  • Laravel macros: Builder|Relation|Collection::firstOption()
  • Controller helpers: unwrapOrAbort() and unwrapOrAbortUnless()
  • Full Rust naming for unwrapping and combinators
  • Interop with a minimal Result (Ok, Err)

Core API

  • Create: fromNullable($v), fromValue($v, $noneValue), ensure($v|callable), fromReturn(callable, args, noneValue)
  • Query: isSome(), isNone(), contains($x), isSomeAnd(fn($v)=>bool), isNoneOr(fn($v)=>bool)
  • Unwrap: unwrap(), expect($msg), unwrapOr($default), unwrapOrElse(fn()=>default), unwrapOrDefault()
  • Map/Chain: map(fn), mapOr($default, fn), mapOrElse(fn()=>default, fn), mapOrDefault(fn), andThen(fn=>Option)
  • Combine: and(Option), or(Option), orElse(fn=>Option) (lazy), xor(Option), zip(Option), zipWith(Option, fn($a,$b)=>x), unzip(), flatten()
  • Match: match(fn($v)=>x, fn()=>y)
  • HTTP: unwrapOrAbort(int $status=404, ?string $message=null), unwrapOrAbortUnless(bool|callable $cond, int $status=404, ?string $message=null)
  • Result interop: okOr($err), okOrElse(fn()=>err), transpose() (Option<Result<T,E>> → Result<Option,E>)

Result API (interop)

  • Types: App\Support\Result\Ok, App\Support\Result\Err
  • Query: isOk(), isErr(), ok(): Option<T>, err(): Option<E>, contains($x), containsErr($e)
  • Map/Chain: map(fn), mapErr(fn), andThen(fn=>Result), mapOr($default, fn), mapOrElse(fn($e)=>default, fn($v)=>x)
  • Combine: and(Result), or(Result), orElse(fn=>Result)
  • Unwrap: unwrap(), unwrapErr(), unwrapOr($default), unwrapOrElse(fn($e)=>x), expect($msg), expectErr($msg), intoOk(), intoErr()
  • Transpose: transpose() (Result<Option,E> → Option<Result,E>)

Laravel Integration

  • App\Providers\OptionServiceProvider registers firstOption() macros:
    • Illuminate\Database\Eloquent\Builder::firstOption()
    • Illuminate\Database\Eloquent\Relations\Relation::firstOption()
    • Illuminate\Support\Collection::firstOption(callable $p=null)
  • Prefer unwrapOrAbort() / unwrapOrAbortUnless() in controllers

Migration Notes

  • Renamed to Rust terms:
    • getOrThrowunwrapOrThrow
    • getOrElseunwrapOr
    • getOrCallunwrapOrElse
  • Prefer Option::fromNullable(...) over fromValue(..., null)

Examples

// Controller-style early return
$user = User::query()->whereKey($id)
    ->firstOption()
    ->unwrapOrAbort(404);

// Compose with combinators
$name = Option::fromNullable($request->string('name'))
    ->map('trim')
    ->filter(fn ($s) => $s !== '')
    ->unwrapOr('Anonymous');

// Result interop
$emailResult = Option::fromNullable($payload['email'] ?? null)
    ->map('strtolower')
    ->okOr('missing-email');

// Pattern match
$label = $maybeUser->match(
    fn ($u) => $u->name,
    fn () => 'Guest',
);

// Typed defaults via Defaultable
use App\Support\Defaultable;

final class Profile implements Defaultable
{
    public function __construct(public string $name)
    {
    }

    public static function default(): self
    {
        return new self('Anonymous');
    }
}

$profile = Option::fromNullable($maybeProfile)
    ->unwrapOrElse([Profile::class, 'default']);
  • Utilities: inspect(fn($v)=>void), cloned()