Git Product home page Git Product logo

luthor's Introduction

Hello

My name is Nabeel. I am a Flutter and Dart developer ๐Ÿ˜Ž!

Follow me on Twitter and LinkedIn

luthor's People

Contributors

exaby73 avatar kasefuchs avatar nerothron avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

Forkers

nerothron fahami

luthor's Issues

`l.list()` does not validate inner values correctly

Take the following code sample:

void main() {
  final v = l.list(validators: [l.number().required()]);
  print(v.validateValue([1, 2, 3, null]));
}

Currently, the above code results in a success case, even though the only validator that exists is a required number validator. This means, null should have been caught and an error should have been returned instead of a success

Add `fromJson` argument

Right now, if you want to convert your validated data into a Dart object, you have to do the conversion manually, or through a package like json_serializable. Take the following code:

class AuthDto {
  final String email;
  final String password;

  const AuthDto({required this.email, required this.password});

  factory AuthDto.fromJson(Map<String, dynamic> json) {
    return AuthDto(email: json['email'] as String, password: json['password'] as String);
  }
}

final v = l.schema({'email': l.string().email().required(), 'password': l.string().min(8).required()});
final rawJson = {'email': '[email protected]', 'password': 'password'};
final result = v.validateSchema(rawJson);

switch (result) {
  case SchemaValidationSuccess(data: final validatedJson):
    final dto = AuthDto.fromJson(validatedJson);
    // Do something with the dto
  case SchemaValidationError(data: _, errors: final errors):
    // Do something with the errors
}

Here we have to manually call fromJson rather than SchemaValidationSuccess giving us the dto in the first place. This proposal would add a fromJson argument to validateSchema and validateSchemaWithFieldName so we can do this:

final v = l.schema({'email': l.string().email().required(), 'password': l.string().min(8).required()});
final rawJson = {'email': '[email protected]', 'password': 'password'};
final result = v.validateSchema(rawJson, fromJson: AuthDto.fromJson);

switch (result) {
  case SchemaValidationSuccess(data: final dto):
    // Do something with the dto. dto is of type `AuthDto`
  case SchemaValidationError(data: _, errors: final errors):
    // Do something with the errors
}

Motivation

Currently, using luthor_generator, we have to manually convert the dto. But ideally, luthor_generator can do this for us using this technique. We don't need to add functionality to luthor but we can rely on code generation to generate this behavior for us instead of adding this argument, but I think this could be useful for those who don't want to use code generation, and just want to use the base package instead.

[luthor_generator] fieldRename and JsonKey name support

Currently, luthor does not support name in JsonKey and fieldRename in JsonSerializable, which prevents luthor from being used in some projects.

For example:

@luthor
@freezed
class TestEntity with _$TestEntity {
  @JsonSerializable(fieldRename: FieldRename.snake)
  const factory TestEntity({
    required String firstTestField,
    @JsonKey(name: "second") required String secondTestField,
  }) = _TestEntity;

  static SchemaValidationResult<TestEntity> validate(Map<String, dynamic> json) => _$validate(json);

  factory TestEntity.fromJson(Map<String, dynamic> json) => _$TestEntityFromJson(json);
}

will generate:

Validator $TestEntitySchema = l.schema({
  'firstTestField': l.string().required(),
  'secondTestField': l.string().required(),
});

but should:

Validator $TestEntitySchema = l.schema({
  'first_test_field': l.string().required(),
  'second': l.string().required(),
});

Return union types

Hello!

One aspect of Zod which works well with TypeScript is the union types returned from parsing/validating a schema:

const input = z.string().safeParse(123);

console.log(input.data) // type error!

if (!input.success) {
  console.log(input.message);
  return;
}

console.log(input.data) // ok!

Based on the readme, at the moment the result doesn't handle this scenario which makes things less type safe. Using freezed unions, you could internally return a Validation union, something like:

final result = l.string().validate('hello');

result.when(
  success: (String value) => print(value),
  error: (String message) => throw Exception(message),
)

Better errors

Currently, luthor gives single strings as error messages, even if you're validating a schema. Ideally, it should return a list of strings for single validations, and a map of strings and list of strings for schema validations.

Current behavior

final v = l.string().email().required();
final r = v.validate(1);
print(r.whenOrNull(error: (e) => e)); // "value is not a string"

final s = l.schema({
  email: l.string.email().required(),
  password: l.string.min(8).required(),
});
final r = v.validate({'email': 1});
print(r.whenOrNull(error: (e) => e)); // "email is not a string"

Expected behavior

final v = l.string().email().required();
final r = v.validate(1);
print(r.whenOrNull(error: (e) => e)); // ["value is not a string", "value is not a valid email"]

final s = l.schema({
  email: l.string.email().required(),
  password: l.string.min(8).required(),
});
final r = v.validate({'email': 1});
print(r.whenOrNull(error: (e) => e)); 
/* 
{
  "email": ["email is not a string", "email is not a valid email"],
  "password: ["password is not a string", "password must be at least 8 characters long", "password is required"]
}
*/

Upon a validation error, luthor still calls `fromJson` which may throw an error

Consider a non-nullable field is validated. If that field doesn't exist, the validation catches it but still tries to call fromJson which may throw a type error if fromJson is expecting a non-null value, which is intended. Single fix is to remove data from SchemaValidationError.

SchemaValidationResult<T> validateSchema<T>(
Map<String, Object?> value, {
FromJson<T>? fromJson,
}) {
final errors = _isValid(null, value);
if (errors != null) {
return SchemaValidationError(
data: fromJson?.call(value) ?? value as T,
errors: errors,
);
}
return SchemaValidationSuccess(data: fromJson?.call(value) ?? value as T);
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.