Domain helpers
JIntent supplies use-case, Either and mapper helpers. Repositories,
persistence, networking and caching are owned by the consuming application. The
counter example’s layering (DTO,
mapper,
repository,
use cases) is optional. Keep
storage-specific types outside UI state and convert expected failures at the
operation boundary.
Either is sealed, so a switch over it is checked for exhaustiveness:
final text = switch (result) { Left(:final value) => 'Failed: $value', Right(:final value) => 'Got $value',};Left and Right compare by value and exact runtime type (type arguments
included), so equality is symmetric.
Validation
Section titled “Validation”JUseCase<INPUT, OUTPUT> and JSyncUseCase<INPUT, OUTPUT> accept validators
through addValidator. Each UseCaseInputValidator<I> returns
Either<Exception, I>.
class PositiveCounter extends JSyncUseCase<int, int> { PositiveCounter() { addValidator((value) => value < 0 ? Left(Exception('Counter must be non-negative')) : Right(value)); }
@override Either<Exception, int> run(int input) => Right(input);}
final result = PositiveCounter().call(3);Call the use case through call (or function-call syntax) to run validation.
Calling run directly bypasses validators. Validators execute synchronously in
registration order and stop at the first Left. Successful validator values
are not passed to later validators or run: all receive the original input.
Thrown exceptions are not converted to Left. Validators are operation
preconditions, not a replacement for server-side authorization.
JUseCaseVoid exposes only run; it has no built-in validator chain.
JValidationUtils (from package:jintent/utils.dart) offers parsing defaults
and range checks, not a general validation framework. See the example’s
validators and
tests.
Mappers
Section titled “Mappers”JMapper<INPUT, OUTPUT> implements IMapper through a single map override:
class CountLabelMapper extends JMapper<int, String> { @override String map(int value) => 'Count: $value';}
final mapper = CountLabelMapper();final label = mapper.transform(2);final labels = mapper.transformList([1, 2]);final sameLabels = [1, 2].mapWith(mapper);transformconverts one input;transformListreturns a new output list.transformDynamicacceptsINPUTorList<INPUT>and throwsArgumentErrorfor other types. Prefer the typed methods when possible.IBiMapper<A, B>definesto(A)andfrom(B)for explicit two-way mapping. Implement and test both directions; invertibility is not enforced.
See the counter mapper and its tests.