Dart and Flutter sealed class generator and annotations, with match methods and other utilities. There is also super_enum compatible API.

Overview

Dart Sealed Class Generator

build build pub pub pub

Generate sealed class hierarchy for Dart and Flutter.

Features

  • Generate sealed class with abstract super type and data sub-classes.
  • Static factory methods. for example Result.success(data: 0).
  • Cast methods. for example a.asSuccess, a.isSuccess or a.asSuccessOrNull.
  • Three types of equality and hashCode generation : data (like kotlin data classes), identity and distinct.
  • Implement data equality with popular equatable library.
  • Support for generics. even types can be mixed.
  • Support for nullable and non-nullable types in null-safe projects.
  • Support for using one sealed type in another.
  • Support for null-safety.
  • Generate toString for data classes.
  • Generate 6 types of different matching methods. like when, maybeWhen and map.

Usage

Add dependencies in your pubspec.yaml file.

dependencies:
  sealed_annotations: ^latest.version

dev_dependencies:
  sealed_generators: ^latest.version

Import sealed_annotations.

import 'package:sealed_annotations/sealed_annotations.dart';

Add part pointing to a file which you want classes be generated in. with .sealed.dart extension.

part 'weather.sealed.dart';

Add @Sealed annotation, and an abstract private class as a manifest for generated code. For example:

@Sealed()
abstract class _Weather {
  void sunny();

  void rainy(int rain);

  void windy(double velocity, double? angle);
}

Then run the following command to generate code for you. If you are developer for flutter:

flutter pub run build_runner build

And if you are developing for pure dart:

dart run build_runner build

The generated code will look like: (the following code is summarised)

abstract class Weather {
  const factory Weather.rainy({required int rain}) = WeatherRainy;

  bool get isRainy => this is WeatherRainy;

  WeatherRainy get asRainy => this as WeatherRainy;

  WeatherRainy? get asRainyOrNull {
    /* ... */
  }

  /* ... */

  R when<R extends Object?>({
    required R Function() sunny,
    required R Function(int rain) rainy,
    required R Function(double velocity, double? angle) windy,
  }) {
    /* ... */
  }

  R maybeWhen<R extends Object?>({
    R Function()? sunny,
    R Function(int rain)? rainy,
    R Function(double velocity, double? angle)? windy,
    required R Function(Weather weather) orElse,
  }) {
    /* ... */
  }

  R? whenOrNull<R extends Object?>({
    R Function()? sunny,
    R Function(int rain)? rainy,
    R Function(double velocity, double? angle)? windy,
    R Function(Weather weather)? orElse,
  }) {
    /* ... */
  }

  R map<R extends Object?>({
    required R Function(WeatherSunny sunny) sunny,
    required R Function(WeatherRainy rainy) rainy,
    required R Function(WeatherWindy windy) windy,
  }) {
    /* ... */
  }

  R maybeMap<R extends Object?>({
    R Function(WeatherSunny sunny)? sunny,
    R Function(WeatherRainy rainy)? rainy,
    R Function(WeatherWindy windy)? windy,
    required R Function(Weather weather) orElse,
  }) {
    /* ... */
  }

  R? mapOrNull<R extends Object?>({
    R Function(WeatherSunny sunny)? sunny,
    R Function(WeatherRainy rainy)? rainy,
    R Function(WeatherWindy windy)? windy,
    R Function(Weather weather)? orElse,
  }) {
    /* ... */
  }
}

class WeatherSunny extends Weather {
  /* ... */
}

class WeatherRainy extends Weather with EquatableMixin {
  WeatherRainy({required this.rain});

  final int rain;

  @override
  String toString() => 'Weather.rainy(rain: $rain)';

  @override
  List<Object?> get props => [rain];
}

class WeatherWindy extends Weather {
  /* ... */
}

Notes:

  • Prefer using factories in super class instead of sub-class constructors. like Whether.rainy() instead of WhetherRainy()
  • Minimize usage of cast methods, most of the time they can be replaced with a match method.

Equality and generated class names

You can choose between three types of equality using @WithEquality(...) annotation. Default equality is data if not specified. This will become default equality for all sub-classes. You can change equality of each sub-class by using this annotation on individual methods.

Equality types:

  • data Equality is implemented with Equatable package. It behaves like kotlin data classes.
  • identity Only identical instances are equal. It's like when you don't implement any specific equality.
  • distinct All the instances are not equal with each other. Even an instance is not equal with itself.

A basic example:

@Sealed()
abstract class _Weather {
  void sunny();

  void rainy(int rain);

  void windy(double velocity, double? angle);
}

In the proceeding example all classes will have data equality. For example if you wanted identity equality for all classes but using distinct equality for windy:

@Sealed()
@WithEquality(Equality.identity)
abstract class _Weather {
  void sunny();

  void rainy(int rain);

  @WithEquality(Equality.distinct)
  void windy(double velocity, double? angle);
}

An abstract super class is generated with name equal to name of manifest class without the underline (here Weather). Each method will become a sub-class. There should be at least one method. sub-class names are based on method name prefixed with super class name (for example WeatherSunny). Naming process can be tailored with use of @WithPrefix and @WithName annotations. Each method argument will become a field in corresponding sub-class. Field names are equal to argument names and field types are equal to argument types or dynamic if not specified. Argument types can be overridden using @WithType annotation for example when type information is not available at build time. Note that you can have nullable and non-nullable fields.

To change prefix of sub-class names which by default is top class name, you can use @WithPrefix annotation. for example:

@Sealed()
@WithPrefix('Hello')
abstract class _Weather {
  void sunny();
}

Now sunny will be named HelloSunny instead of the default WeatherSunny. You can use @WithPrefix('') to remove all prefix from sub-class names.

To change sub-class names directly you can use @WithName annotation. It will override WithPrefix if specified. for example:

@Sealed()
abstract class _Weather {
  @WithName('Hello')
  void sunny();
}

Now sunny will be named Hello instead of the default WeatherSunny. This is useful if you want not to use prefix for some items.

Almost all methods on sealed classes use short names extracted from manifest method names. Full sub-class names are not used. It is recommended not to use sub-classes directly. There are factory methods for each item on super class.

Generic Usage

For generic sealed classes you should write manifest class like a generic class which you are implementing.

It is recommended that if you want nullable generic fields, declare a generic parameter as T extends Base? and use T without nullability suffix. If you want non-nullable generic fields declare a generic parameter as T extends Base and use T without nullability suffix. If you don't specify upper bound it will default to Object? so your generic types will be nullable.

import 'package:sealed_annotations/sealed_annotations.dart';

part 'result.sealed.dart';

@Sealed()
abstract class _Result<D extends num> {
  void success(D data);

  void error(Object exception);
}

Or you can have multiple generic types and even mix them.

import 'package:sealed_annotations/sealed_annotations.dart';

part 'result.sealed.dart';

@Sealed()
abstract class _Result<D extends num, E extends Object> {
  void success(D data);

  void error(E exception);

  void mixed(D data, E exception);
}

Dynamic types and Using one sealed type in another

Consider you have a sealed result type like:

@Sealed()
abstract class _Result<D extends Object> {
  /* ... */
}

You want to use this type in another sealed type.

@Sealed()
abstract class _WeatherInfo {
  void fromInternet(Result<WeatherData> result);
}

If you generate for WeatherInfo you will see that result has dynamic type. It is because Result itself is not code generated at build time.

You should use @WithType annotation.

@Sealed()
abstract class _WeatherInfo {
  void fromInternet(@WithType('Result<WeatherData>') result);

  // you can also have nullable types.
  void nullable(@WithType('Result<WeatherData>?') result);
}

Hierarchy Feature

If Sealed classes are in the same file you can reference them directly using their manifest class name. This is to avoid @WithType annotation and better refactoring capability.

@Sealed()
abstract class _Apple {
  void eat();
}

@Sealed()
abstract class _Banana {
  void eat();
}

@Sealed()
abstract class _Basket {
  void friends(_Apple? apple, _Banana? banana);

// or equivalently
// void friends(@WithType('Apple?') apple, @WithType('Banana?') banana);
}

And for generic case:

@Sealed()
abstract class _Result<D extends num> {
  void success(D data);

  void error(Object exception);
}

@Sealed()
abstract class _Basket {
  void hold(_Result<int> x);

// or equivalently:
// void hold(@WithType('Result<int>') x);
}

@WithType annotation will override hierarchy feature if present.

Common Fields

Sometimes you need some fields to be present in all of your sealed classes. For example consider making a sealed class for different types of errors, and all of them are required to have code and message. It is very annoying to add code and message to all of sealeds manually. Also if you have an error object you are unable to get its code or message without using cast or match methods. Here you can use common fields.

To declare a common field you can add a getter or a final field to a manifest class, and it will automatically be added to all of your sealed classes. for example:

@Sealed()
abstract class _ApiError {
  // using getter
  String get message;

  // using final field
  final String? code = null;

  // code and message will be added to this automatically
  void internetError();

  void badRequest();

  void internalError(Object? error);
}

You can also use a constructor in pair with final fields equivalently.

common fields are available on ApiError objects as well as it's sub-classes.

If you specify common fields in your seaeld classes it has no effect. for example:

@Sealed()
abstract class _Common {
  Object get x;

  // one and two will have identical signatures
  void one(Object x);

  void two();
}

You can use sub-class of common field type in sealed classes. For example:

@Sealed()
abstract class _Common {
  Object get x;

  // x has type int
  void one(int x);

  // x has type String
  void one(String x);

  // x has type Object
  void three();
}

common fields also works with other constructs of dart_sealed like generics and @WithType. for example:

@Sealed()
abstract class _Common {
  @WithType('num')
  dynamic get x; // you can omit dynamic

  // x has type int
  void one(@WithType('int') dynamic x); // you can omit dynamic

  // x has type num
  void two();
}

and, for example:

@Sealed()
abstract class _Result<D extends num> {
  Object? get value;

  void success(D value);

  void error();
}

Ignoring Generated Files

It is recommended to ignore generated files on Git. Add this to your .gitignore file:

*.sealed.dart

To exclude generated files from dart analysis, add this to your analysis_options.yaml file:

analyzer:
  exclude:
    - lib/**/*.sealed.dart
Comments
  • Common fields

    Common fields

    add capability to add common fields. for example:

    import 'package:sealed_annotations/sealed_annotations.dart';
    
    part 'common.sealed.dart';
    
    @Sealed()
    abstract class _ApiError {
      String get message;
    
      String? get code;
    
      void internetError();
    
      void badRequest();
    }
    

    By now the best way to implement such a behavior is to use extension methods on a conventional seald. like this:

    import 'package:sealed_annotations/sealed_annotations.dart';
    
    part 'sobhan.sealed.dart';
    
    @Sealed()
    abstract class _ApiError {
      void internetError(String message, String? code);
    
      void badRequest(String message, String? code);
    }
    
    extension on ApiError {
      String get message => map(
            internetError: (e) => e.message,
            badRequest: (e) => e.message,
          );
    
      String? get code => map(
            internetError: (e) => e.code,
            badRequest: (e) => e.code,
          );
    }
    

    or by casting to dynamic in extension function:

    extension on ApiError {
      String get message => (this as dynamic).message as String;
     
      String? get code => (this as dynamic).code as String?;
    }
    

    also the question about default values remains, for example consider internetError code is always null or any other value.

    enhancement 
    opened by FatulM 27
  • Suggestion to add map method and...

    Suggestion to add map method and...

    Hi :wave:

    I would recommend to add map methods if the user generates everything @WithWrap(). For now, I am forced every time to add this manually. Map method is useful by copyWith() method.

    //...
      R map<R extends Object?>({
        required R Function() loading,
        required R Function(ResultError<T, E> error) error,
        required R Function(ResultData<T, E> data) data,
      }) {
        final result = this;
        if (result is ResultLoading<T, E>) {
          return loading();
        } else if (result is ResultError<T, E>) {
          return error(result);
        } else if (result is ResultData<T, E>) {
          return data(result);
        } else {
          throw AssertionError();
        }
      }
    
      R mapOrElse<R extends Object?>({
        R Function()? loading,
        R Function(ResultError<T, E> error)? error,
        R Function(ResultData<T, E> data)? data,
        required R Function(Result<T, E> result) orElse,
      }) {
        final result = this;
        if (result is ResultLoading<T, E>) {
          return loading != null ? loading() : orElse(result);
        } else if (result is ResultError<T, E>) {
          return error != null ? error(result) : orElse(result);
        } else if (result is ResultData<T, E>) {
          return data != null ? data(result) : orElse(result);
        } else {
          return orElse(result);
        }
      }
    //...
    

    Instead of functions, I think the getters are better for cleaner code syntax. Example:

      bool get isLoading => this is ResultLoading<T>;
      bool get isError => this is ResultError<T>;
      bool get isData => this is ResultData<T>;
    
      ResultLoading<T> get asLoading => this as ResultLoading<T>;
      ResultError<T> get asError => this as ResultError<T>;
      ResultData<T> get asData => this as ResultData<T>;
    
      ResultLoading<T>? get asLoadingOrNull {
        final result = this;
        return result is ResultLoading<T> ? result : null;
      }
    
      ResultError<T>? get asErrorOrNull {
        final result = this;
        return result is ResultError<T> ? result : null;
      }
    
      ResultData<T>? get asDataOrNull {
        final result = this;
        return result is ResultData<T> ? result : null;
      }
    

    and then you can use it.

    final value = data.asData.value;
    // Instead
    final value = data.asData().value; 
    

    Of course, it's a taste thing. It's just my opinion.

    And Dart Sealed Class Generator needs updated analyzer to 1.7.0 => 2.0.0 it conflicts with other packages for example with most one popular Freezed or json_serializable. It would make easier life to config pubspec.yaml file for beginners :smiley:

    And factory constructors prefer declaring const constructors on @immutable classes.

    enhancement 
    opened by iamarnas 26
  • Support for nullable optional parameters

    Support for nullable optional parameters

    After working with this package for a while, I have noticed that the package doesn't support for optional parameters. I think users will have a better experience if they do not have to submit optional parameters.

    opened by payam-zahedi 9
  • Mention to ignore generated files on .gitignore and analysis_options.yaml

    Mention to ignore generated files on .gitignore and analysis_options.yaml

    It is worth mentioning to exclude generated files in the README.md:

    For .gitignore:

    *.sealed.dart
    

    For analysis_options.yaml

    analyzer:
      exclude:
        - **.sealed.dart
    
    opened by SaeedMasoumi 4
  • Functional types are not supported as field types

    Functional types are not supported as field types

    here is the code for the sealed class

    import 'package:flutter/material.dart';
    import 'package:rekab_delivery/src/util/consumable.dart';
    import 'package:rekab_delivery/src/util/typedefs.dart';
    import 'package:rekab_delivery/src/widget/src/utils/message.dart';
    import 'package:sealed_annotations/sealed_annotations.dart';
    
    part 'login_state.sealed.dart';
    
    @Sealed()
    abstract class _LoginState {
      void initial();
      void loading();
      void success(List<String> countries);
      void error(Message msg);
      void invalidNumber();
      void retry(VoidCallback callback);
    }
    

    and here is the error i get when running build_runner

    [INFO] Generating build script...
    [INFO] Generating build script completed, took 675ms
    
    [INFO] Initializing inputs
    [INFO] Reading cached asset graph...
    [INFO] Reading cached asset graph completed, took 112ms
    
    [INFO] Checking for updates since last build...
    [INFO] Checking for updates since last build completed, took 670ms
    
    [INFO] Running build...
    [INFO] 1.2s elapsed, 1/3 actions completed.
    [INFO] 2.2s elapsed, 1/3 actions completed.
    [INFO] 3.3s elapsed, 1/3 actions completed.
    [INFO] 10.7s elapsed, 1/3 actions completed.
    [INFO] 13.3s elapsed, 2/3 actions completed.
    [INFO] 14.5s elapsed, 8/9 actions completed.
    [SEVERE] sealed_generators:sealed_generators on lib/src/cubits/login/request/code/login_state.dart:
    
    "SealedError{message={internal error},cause={check failed}}"
    [INFO] Running build completed, took 14.6s
    
    [INFO] Caching finalized dependency graph...
    [INFO] Caching finalized dependency graph completed, took 58ms
    
    [SEVERE] Failed after 14.7s
    pub finished with exit code 1
    

    I tried different things found out whenever I use the type VoidCallback or a generic type that has that type like Consumable<VoidCallback> as the method argument, code generation fails

    bug good first issue 
    opened by easazade 3
  • How can I convert super enums to this package

    How can I convert super enums to this package

    I have this super_enum and the advise was to convert this to this package. I am wondering how all this will convert? Any help is appreciated...

    import 'package:super_enum/super_enum.dart';
    
    part 'emission_test_bloc_state.super.dart';
    
    @superEnum
    enum _EmissionTestBlocState {
      @object
      Disconnected,
      @object
      NoVinFailure,
    
      @object
      NoInternet,
    
      @Data(fields: [
        DataField<String>('vin'),
      ])
      Waiting,
      @Data(fields: [
        DataField<String>('request'),
      ])
      RequestMILStatus,
      @Data(fields: [
        DataField<String>('request'),
      ])
      RequestDTC,
      @object
      RequestRedinessMonitor,
      @Data(fields: [
        DataField<dynamic>('dtcs'),
        DataField<dynamic>('status'),
      ])
      TestFaliure,
      @Data(fields: [
        DataField<String>('message'),
        DataField<dynamic>('status'),
      ])
      TestPassed,
      @Data(fields: [
        DataField<dynamic>('status'),
      ])
      NotCompleted,
      @Data(fields: [
        DataField<String>('request'),
      ])
      RequestClearDTC,
      @object
      ErrorCodesCleared,
    }
    
    opened by ride4sun 0
  • Breaks with analyzer 5.0.0

    Breaks with analyzer 5.0.0

    Running dart run build_runner build with a dependency on analyzer v5.0.0 gives the following errors. Dropping back to 4.7.0 works fine.

    
    ../../../../.pub-cache/hosted/pub.dartlang.org/sealed_generators-1.13.0/lib/src/manifest/manifest_reader_builder.dart:40:12: Error: The getter 'isEnum' isn't defined for the class 'ClassElement'.
     - 'ClassElement' is from 'package:analyzer/dart/element/element.dart' ('../../../../.pub-cache/hosted/pub.dartlang.org/analyzer-5.0.0/lib/dart/element/element.dart').
    Try correcting the name to the name of an existing getter, or defining a getter or field named 'isEnum'.
          !cls.isEnum && !cls.isMixin && !cls.isMixinApplication,
               ^^^^^^
    ../../../../.pub-cache/hosted/pub.dartlang.org/sealed_generators-1.13.0/lib/src/manifest/manifest_reader_builder.dart:40:27: Error: The getter 'isMixin' isn't defined for the class 'ClassElement'.
     - 'ClassElement' is from 'package:analyzer/dart/element/element.dart' ('../../../../.pub-cache/hosted/pub.dartlang.org/analyzer-5.0.0/lib/dart/element/element.dart').
    Try correcting the name to the name of an existing getter, or defining a getter or field named 'isMixin'.
          !cls.isEnum && !cls.isMixin && !cls.isMixinApplication,
                              ^^^^^^^
    ../../../../.pub-cache/hosted/pub.dartlang.org/sealed_generators-1.13.0/lib/src/manifest/manifest_reader.dart:148:28: Error: The getter 'element' isn't defined for the class 'DartType'.
     - 'DartType' is from 'package:analyzer/dart/element/type.dart' ('../../../../.pub-cache/hosted/pub.dartlang.org/analyzer-5.0.0/lib/dart/element/type.dart').
    Try correcting the name to the name of an existing getter, or defining a getter or field named 'element'.
        final reference = type.element;
                               ^^^^^^^
    
    
    opened by nullrocket 2
  • Generate constant for types without arguments

    Generate constant for types without arguments

    In my project I have a sealed class with an empty subtype that I use as default argument in a constructor. For that to work I need a static constant of that type, which I currently have to create myself as a top level field. This PR allows the writer to generate those constants as static const field inside the sealed class.

    Edit: I've noticed that my first commit didn't produce correct Dart code, so I've fixed that in the second one. Unfortunately for that I needed to remove the factory method that was previously generated for such subtypes, which is a breaking change. If this isn't acceptable, this could be solved with an optional parameter on the @Sealed() annotation controlling the code generation. But before I go there, I'll wait for feedback if this is a welcome addition at all here first.

    Excerpt of generated code:

    abstract class Weather {
      static const Weather sunny = WeatherSunny();
      
      const factory Weather.rainy({required int rain}) = WeatherRainy;
    }
    
    opened by Almighty-Alpaca 0
  • copyWith generation

    copyWith generation

    Generate copyWith method for sealed classes.

    We should disallow generic type change in copy with method to make life easier.

    For nullable types we have two approaches:

    For example:

    class Base{
    void one(int? x);
    }
    

    Freezes way of implementation:

    this will generate code which needs two levels of inheritance for each copy with method and is not very straight forward.

    we have this:

    /// @nodoc
    abstract class $BaseCopyWith<$Res> {
      factory $BaseCopyWith(Base value, $Res Function(Base) then) =
          _$BaseCopyWithImpl<$Res>;
    }
    
    /// @nodoc
    class _$BaseCopyWithImpl<$Res> implements $BaseCopyWith<$Res> {
      _$BaseCopyWithImpl(this._value, this._then);
    
      final Base _value;
    
      // ignore: unused_field
      final $Res Function(Base) _then;
    }
    

    then this:

    /// @nodoc
    abstract class _$OneCopyWith<$Res> {
      factory _$OneCopyWith(_One value, $Res Function(_One) then) =
          __$OneCopyWithImpl<$Res>;
    
      $Res call({int? x});
    }
    
    /// @nodoc
    class __$OneCopyWithImpl<$Res> extends _$BaseCopyWithImpl<$Res>
        implements _$OneCopyWith<$Res> {
      __$OneCopyWithImpl(_One _value, $Res Function(_One) _then)
          : super(_value, (v) => _then(v as _One));
    
      @override
      _One get _value => super._value as _One;
    
      @override
      $Res call({
        Object? x = freezed,
      }) {
        return _then(_One(
          x: x == freezed
              ? _value.x
              : x // ignore: cast_nullable_to_non_nullable
                  as int?,
        ));
      }
    }
    

    we have this:

    @JsonKey(ignore: true)
      _$OneCopyWith<_One> get copyWith => throw _privateConstructorUsedError;
    

    which will be overriden by:

      @JsonKey(ignore: true)
      @override
      _$OneCopyWith<_One> get copyWith =>
          __$OneCopyWithImpl<_One>(this, _$identity);
    

    And using optionals:

    class Optional<T> {
      final bool isValid;
      final T? _value;
    
      T get value => _value as T;
    
      const Optional()
          : isValid = false,
            _value = null;
      const Optional.value(this._value) : isValid = true;
    }
    
    class Person {
      final String? name;
    
      Person(this.name);
    
      Person copyWith({Optional<String?> name = const Optional()}) =>
          Person(name.isValid ? name.value : this.name);
    }
    

    But when you want to set to any thing you should use optional ...

    Special thanks to @iamarnas for his recommendations.

    enhancement 
    opened by FatulM 1
  • Use manifest class constructor for common fields

    Use manifest class constructor for common fields

    Add ability to use manifest class constructor for common fields.

    
    @Sealed()
    abstract class _ApiError {
      _ApiError({String message, String? code,});
    
      void internetError();
    
      void badRequest();
    
      void internalError(Object? error);
    }
    

    Complexities arise when combining constructor defined common fields and member defined ones. Also this feature should default values (static and dynamic) and overridden dynamic types.

    Special thanks to @iamarnas for his recommendations.

    enhancement 
    opened by FatulM 1
Releases(v1.13.0)
Owner
6thSolution
6thSolution
A new Flutter project. Use of Padding Class(Widget) and Card Class (Widget)

Use_Of_Card_And_Padding_Class A new Flutter project. Use of Padding Class(Widget) and Card Class (Widget) Getting Started This project is a starting p

Avinandan Bose 1 Mar 18, 2022
Dart Class Diagram Generator

Dart Class Diagram Generator A small command line utility to generate a class (UML or similar) diagram from a Dart package. Examples Below is a UML di

George Lesica 118 Dec 29, 2022
Tinder-like class that allows dogs to pair with other dogs as play buddies and have fun(:

Paw-Tindr Tinder-like class that allows dogs to pair with other dogs as play buddies and have fun(: Setting Up Firebase Follow steps mentioned (here)[

null 3 Dec 15, 2022
JSON formatted API Get, Patch, Put, Post, Delete methods implemented as a dummy.

json_api_handle A new Flutter project. Getting Started This project is a starting point for a Flutter application. A few resources to get you started

Md. Sabik Alam Rahat 4 Nov 13, 2022
Learn how to use Dart List Utility Methods in Flutter

Flutter Tutorial - List Utility Methods Learn how to use Dart List Utility Metho

Behruz Hurramov 0 Dec 29, 2021
Ruqe brings the convenient types and methods found in Rust into Dart, such as the Result, Option, pattern-matching, etc.

ruqe Ruqe brings the convenient types and methods found in Rust into Dart, such as the Result, Option, pattern-matching, etc. Additionally, the librar

Alexander Nitiola 12 Dec 28, 2022
Superpowers for Dart. Collection of useful static extension methods.

If you miss an extension, please open an issue or pull request Resources: Documentation Pub Package GitHub Repository On this page you can find some o

Simon Leier 955 Jan 8, 2023
A dart package for many helper methods fitting common situations

Basic Utils A dart package for many helper methods fitting different situations. Table of Contents Basic Utils Table of Contents Preamble Install pubs

null 275 Jan 5, 2023
Startup-Name-Generator-App-in-Flutter - Business Startup Name Generator App in Flutter

Business Startup Name Generator App #About APP: A simple mobile app that generat

AHSAN SIDDZ 0 Jan 30, 2022
A package help you to make api call and handle error faster, also you can check for internet before call api.

http_solver ##not for production use, only for learning purpose. A package help you to make api call and handle error faster, also you can check for i

Abdelrahman Saed 1 Jun 18, 2020
The easiest way to use navigation, context less and useful methods.

Starlight Utils The easiest way to use navigation, context less and useful methods. Features Name Status Context Less Navigation Service ✅ Context Les

Ye Myo Aung 5 Jul 10, 2022
The Integration Test Helper has pre-configured methods that allow for faster test deployment for end to end (e2e) test coverage.

The Integration Test Helper has pre-configured methods that allow for faster test deployment for end to end (e2e) test coverage (using Android and iOS

The Mobile Applications Community 2 Apr 7, 2022
Hive Wait provide a Hive repository to calling methods in the box as async.

Hive Wait provide a Hive repository to calling methods in the box as async.

Giáo Hồ 1 May 10, 2022
A flutter/dart package that allows developer to develop shiSock client for there application.

A package which allow developers to develop the shiSock client for the there flutter android app. Using flutter-shiSock developers can develop a chat application very easily. It can also be used in app in which we need real time data flow.

shiSock 0 Apr 7, 2022
A Dart client for FusionAuth, Flutter compatible

FusionAuth Dart Client If you're integrating FusionAuth with a Dart or Flutter application, this library will speed up your development time. For addi

FusionAuth 9 Dec 14, 2022
Simple and complete Flutter hooks testing utilities that encourage good testing practices.

Flutter Hooks Testing Library Simple and complete Flutter hooks testing utilities that encourage good testing practices. Inspired by react-hooks-testi

Daichi Furiya 24 Dec 2, 2022
Nebula makes your Flutter development journey easier by providing helper widgets, utilities and abstractions.

Nebula makes your Flutter development journey easier by providing helper widgets, utilities and abstractions.

Aldrin's Art Factory 1 Apr 21, 2022