generators_lite 1.0.4
generators_lite: ^1.0.4 copied to clipboard
Use the power of automatic code generation for Dart.

Start coding with multiple generators working at once powered by package:build_runner
.
Currently includes ready-to-use generators for Assets, I18N, Data Classes and Icon Fonts.
Getting Started #
This package relies on Dart package:analyzer
to format generated code.
It provides a unified way to use all of the featured generators. Currently featuring:
-
Assets generator. Used for utilizing autocompletion of the native file structure.
-
I18N generator. Primarily used for utilizing autocompletion of the files with translations, but can also be used for any type of Dart code conversion from strings.
-
Data Class generator. Used for generating all-in-one Dart classes from provided class fields.
-
Icon Fonts generator. Used for real-time generation of a webfont from
.svg
files. Also utilizes autocompletion of the nested icons like an assets generator.
Installation #
This package is intended to support the development of Dart projects with
package:build_runner
. In general, put it under dev_dependencies in
your pubspec.yaml
.
dev_dependencies:
build_runner: any
generators_lite:
Alternatively, you can use plain console commands to do all the same things. Enable the package globally and use it as a console tool:
dart pub global activate generators_lite
generate <command> [arguments]
Or call the package directly:
dart run generators_lite:main <command> [arguments]
Command is pointing to a generator to be used and arguments are passed directly to that generator. For example:
generate assets --import-path source/assets --export-path lib/assets.g.dart
generate i18n -i source/i18n -e lib/i18n.g.dart
generate models -i models.json -e lib/models.g.dart
generate icons -i source/icons -e lib/icons.g.dart
Usage #
This package is configured using a build.yaml
file. See the
package:build_config
README for more information on this file.
To use all files under your current package and not only files in lib
,
set build.yaml
sources section as following. See also Example
tab for a
complete example on build.yaml
file.
# yaml-language-server: $schema=./build.yaml
targets:
$default:
sources:
include:
- $package$
- lib/$lib$
- '**'
exclude:
- .dart_tool/**
NOTE: Because of the limitations on the
package:build_runner
, there can only be one predefined generated file when using aggregate builders. So, in terms of straightforwardness, every generator generates only one single file. This behavior may change in the future.
To run the generator, you want to run the following command:
dart run build_runner build --delete-conflicting-outputs
To make things even easier, you can also setup VS Code task
for package:build_runner
. This task can also be automatically run if you
allow the c
command.
See this example on tasks.json
for a convenient way to setup such task.
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"type": "shell",
"label": "build_runner",
"command": "flutter",
"args": [
"pub",
"run",
"build_runner",
"watch",
"--delete-conflicting-outputs",
"--low-resources-mode"
],
"isBackground": true,
"presentation": {
"echo": true,
"reveal": "silent",
"focus": false,
"panel": "shared",
"showReuseMessage": true,
"clear": false
},
"problemMatcher": ["$dart-build_runner"],
"runOptions": {
"runOn": "folderOpen"
}
}
]
}
The rest of this section provides detailed instructions on how to use each generator from this package.
Assets Generator #
All this generator does is migrate a file structure from the provided
import_path
to the nested Dart classes.
By default it omits any extension in the file name, but if there are two or more files with the same name and different extensions, the extensions are also added to the group keys.
To use this generator, you also need to specify fetched assets in your
pubspec.yaml
.
flutter:
assets:
- assets/
- assets/nested_folder/
The Assets generator may also have the following keys:
- import_path: The path that leads to the directory to migrate file
structure from. Defaults to
assets
. - export_path: The path that leads to the file that is being generated.
Defaults to
lib/assets.g.dart
. - export_encoding: The encoding used for writing the
.dart
files. Defaults toutf-8
. - base_name: The name of the generated class. Defaults to
Assets
. - convert: If the file names should be converted to
camel case. Disabling this option will prevent any changes
to be made to the file names. Be certain to pass valid Dart names or the
generation will be likely to fail. Defaults to
true
.
I18N Generator #
This generator grounds on an abstract locale, which extends a global abstract base, just like it's nested groups. Optionally, each group can also be modified in a default (unnamed) locale. If there is no default locale, the abstract locale is automatically resolved with all locales provided.
Each locale can be accessed through initialized constant class instance, or
through the call to a special generated Enum
values.
If use_flutter
is true, the I18NLocalizations
class is also generated,
providing a context-dependent interface to access current locale from Flutter
widgets. This also requires providing the localization delegate like so:
MaterialApp(
supportedLocales: I18NLocale.values.map((final _) => _.locale),
localizationsDelegates: const <LocalizationsDelegate<Object?>>[
I18NLocalizations.delegate
],
)
Then, to access the current localization, you would simply write:
final I18N $ = I18NLocalizations.of(context);
To start, we need to mention a few points on groups:
- Each group can be nested indefinitely using getters.
- Each group entry can be a getter or a method, which is derived from the entry key itself. By default, all entries are getters, but if an entry key ends with brackets, it will be rendered as a method.
- If a group entry is a method, it can have any amount of parameters specified. But it is important to match these parameters between locales, including the abstract one.
- If a group entry key has a type specified, this type will override the possible automatically derived return type.
- If a group entry value is multiline, it will be rendered within the function body. And because of that, it will require a return type specified.
- If you want to access the parent group from within the nested group, you can
do that by using the
$
key.
The algorithm for fetching files under import_path
directory:
-
Treat the part in the file name after the last underscore as a locale.
- If only one file name of all doesn't have an underscore it is treated as a part of an abstract locale and other ones are treated regularly.
- If more than one file name doesn't have an underscore, all file names are treated as locales. And the one without name is treated as an abstract one.
-
Process the tree structure for each fetched locale, including abstract one.
- If there is only one file for a locale at a directory, file's parent directories stay present, but the file name is omitted, and the grouping starts inside this file.
- If there is more than one file for a locale at a directory, file's parent directories, as well as the name of the file, stay present, and grouping starts one layer up from inside of the file.
-
Check that all of the locales match keys, including abstract one.
- There is an error thrown, if actual locale has keys that neither the other locales have, nor the abstract one.
- The keys, that are not present in the abstract locale, are automatically resolved from the actual locales and added as abstract getters.
-
Check the returning types in the abstract locale.
- Each locale can have its own returning types for group getters, but the abstract locale will always be covariant.
The I18N generator may also have the following keys:
- import_path: The path that leads to the directory with localizations to
be generated. Defaults to
i18n
. - export_path: The path that leads to the file that is being generated.
Defaults to
lib/i18n.g.dart
. - export_encoding: The encoding used for writing the
.dart
files. Defaults toutf-8
. - encoding: The encoding used for reading the
.json
and.yaml
files. Defaults toutf-8
. - base_name: The name of the generated class. Defaults to
I18N
. - convert: If the group keys should be converted to
camel case. Disabling this option will prevent any changes
to be made to the key names. Be certain to pass valid Dart names or the
generation will be likely to fail. Defaults to
true
. - only_language_code: Ensure that locales should only use their language
codes. Defaults to
true
. - base_class_name: The name of the class, that will be used as an abstract
base for generated groups. You may also specify any necessary
imports
needed to import that class. Defaults to null. - enum_class_name: The name of the generated
Enum
. Defaults toI18NLocale
. - serialize: If the generated classes should be serialized using
fromMap
. Defaults tofalse
. - use_flutter: If the generated results are intended to be used with
Flutter. Thus, whether Localizations class and it's Localizations Delegate
should be generated. Defaults to
true
. - localizations_class_name: The name of the I18N Localizations class
implementation. Only used if
use_flutter
is true. Defaults toI18NLocalizations
. - delegate_class_name: The name of the Localizations Delegate class
implementation. Only used if
use_flutter
is true. Defaults toI18NDelegate
. - delegate_fallback_locale: The locale that will be used as a fallback in
Localizations Delegate. Should be the exact match of one of the generated
locales. Only used if
use_flutter
is true. Defaults to the first locale generated. - imports: An iterable or a single string to add as import to the
generated file. Defaults to import
package:meta
.
Data Class Generator #
This generator creates all-in-one classes directly from the predefined config.
To use this generator, you also need to put package:json_converters_lite
under dependencies in your pubspec.yaml
.
dependencies:
json_converters_lite:
The config example is the following:
{
// The name of the class.
"Address": {
// The dart name of the class.
"name": "AddressModel",
// The doc for the class.
"doc": "The model of an address.",
// The properties of each field.
"fields": {
"id": {
"type": "int",
"default": null,
"doc": "The identificator of this address.",
"nullable": true,
"compare": true
},
"postal_code": {
// The dart name will be this value instead of the field key.
"name": "postCode",
"type": "int",
"default": null,
"doc": null,
"nullable": false,
"compare": false
},
"companies": {
// Implementation of the one-to-many relationship.
"type": "Company[]",
"default": [],
"doc": null,
"nullable": false
}
},
"instances": {
"address": {
"id": 1,
"postCode": 12345,
"companies": [
"company"
]
}
}
},
// The name of the other class.
"Company": {
// The dart name of the other class.
"name": "CompanyModel",
"doc": null,
"fields": {
"registry_number": {
"type": "int",
"default": null,
"doc": null,
"nullable": false,
"compare": true
},
"address_id": {
"type": "int",
"default": null,
"doc": null,
"nullable": false,
"compare": false
},
"address": {
// Implementation of the many-to-one relationship.
"type": "Address",
"default": null,
"doc": null,
"nullable": true
}
},
"instances": {
"company": {
"registry_number": 123,
"address_id": "address.id",
"address": "address"
}
}
}
}
The config contains all of the classes to be generated. Each class contains
fields
key to set the fields of the class, and, optionally, an instances
key to create instances of this class from fields
and their values. Each
class and each field can also contain any of the properties listed below.
The properties of the class may optionally specify:
- name: The custom Dart name for the generated class. Defaults to the key
of the class in the outer layer. If generator
convert
option is also true, formats the key to camel case, otherwise be sure to pass valid Dart name or the generation will be likely to fail. - doc: The documentation for the generated class. If none is specified, uses the mock up one.
- static_keys: If the static fields with the names of actual field keys
should be generated. Defaults to
true
. - to_json: If
toJson
andfromJson
serialization methods should also be created for each model. Defaults totrue
.
The properties of each field may optionally specify:
-
type: The type of the field, works like
Enum
. If specified a square brackets at the end, will be anIterable
of the same type. For, example:"type": "integer" // will be an integer "type": "integer[]" // will be an iterable of integers "type": "enum" // will raise an error "type": "enum[a,b,c]" // will be an Enum "type": "flag[a,b,c]" // will be an iterable of Enums
Currently, type can be one of the following:
- object,
- enum, which is later generated from it's values in square brackets,
- bool,
- int,
- float, which is converted to
double
, - str, which is converted to
String
, - datetime, which is converted to
DateTime
, - timedelta, which is converted to
Duration
, - or other data class that is being currently generated.
-
name: The custom Dart name for the generated field. Defaults to the key of the field in the middle layer. If generator
convert
option is also true, formats the key to camel case, otherwise be sure to pass valid Dart name or the generation will be likely to fail. -
doc: The documentation for the generated field. If none is specified, uses the mock up one.
-
default: The default value of this field. This value should be a serialized value of this field's type, which is then deserialized and rendered correctly during generation proccess.
-
nullable: If the field can be nullable. Defaults to
true
. -
required: If the field is required. Defaults to
true
, if field has nodefault
value specified and field isnullable
. -
copy: If the field should be included in
copyWith
orcopyWithNull
methods. Defaults totrue
. -
serialize: If the field should be included in
toMap
method. Defaults totrue
. -
deserialize: If the field should be included in
fromMap
method if it is not required. Defaults totrue
. -
compare: If the field should participate in
compareTo
method implementaion. Defaults tofalse
. -
equality: If the field should be added to
== operator
andhashCode
. Can be a bool or a string of the following values:- none, if the field should not be added to equality,
- ordered (default), if the equality should be added as
IterableEquality
for iterable fields and== operator
for regular ones, - unordered, if the equality should be added as
UnorderedIterableEquality
for iterable fields and== operator
for regular ones.
-
to_string: If the field should be added to the
toString
method. Defaults totrue
. -
check_type: If value type should be checked on
deserialize
and replaced forchek_type_default
if needed. Defaults totrue
. -
check_type_default: The default value of this field if
check_type
resolves to false. This value should be a serialized value of this field's type, which is then deserialized and rendered correctly during generation proccess. If no value is specified, thedefault
value is used instead. -
cast_iterable: If the iterable value
type
should be processed ondeserialize
usingIterable.cast
instead ofIterable.whereType
. Defaults tofalse
.
Each of the generated classes has the following parts:
- constructor
- fields
- copyWith, if any of the class fields has
copy
property set totrue
. - copyWithNull, if any of the class fields has
copy
andnullable
properties set totrue
. - toMap, if any of the class fields has
serialize
property set totrue
. - fromMap, if any of the class fields has
serialize
property set totrue
. - comparable, if any of the class fields has
compare
property set totrue
. - == operator
- hashCode
- toString
The way serialization works is by using the package:json_converters_lite
for handling serialization of basic fields and custom generated converters for
fields with other data classes. Thus, each generated data class has it's own
converter generated.
Also, if class has had any Enum
fields specified, these fields are rendered
on their own at the top of the generated file.
The Data Class generator may also have the following keys:
- import_path: The path that leads to the file or directory to get the
info about generated classes from. Defaults to
models
. - export_path: The path that leads to the file that is being generated.
Defaults to
lib/models.g.dart
. - export_encoding: The encoding used for writing the
.dart
files. Defaults toutf-8
. - encoding: The encoding used for reading the
.json
and.yaml
files. Defaults toutf-8
. - convert_field_names: If the field names should be converted to
camel case. Disabling this option will prevent any changes
to be made to the field names. Be certain to pass valid Dart names or the
generation will be likely to fail. Defaults to
true
. - convert_class_names: If the class names should be converted to
camel case. Disabling this option will prevent any changes
to be made to the class names. Be certain to pass valid Dart names or the
generation will be likely to fail. Defaults to
false
. - assign_field_types: If the unknown field types should be resolved from
default values. Defaults to
true
. - include_null_fields: If the fields with null values should be added in
toMap
. Defaults totrue
. - empty_required_iterables: If the required iterable fields with null values
should be replaced with empty iterable in
fromMap
. Defaults totrue
. - imports: An iterable or a single string to add as an import to the
generated file. By default, imports
package:json_converters_lite
.
Icon Fonts Generator #
This generator depends on the fantasticon js package to generate a webfont itself. So, to use this generator, you need to have Node.JS installed on your machine. Apart from that, it's all the same as the previous ones.
The .svg
icons are taken recursively from the specified import_path
. The
initial file structure is preserved and generated as nested classes later.
NOTE:
.svg
files should be normalized before processing with this generator. To do this, you can use tools like svgo. Unnormalized.svg
may lead to unexpected results including crashes.
To use this generator, you also need to specify generated font in your
pubspec.yaml
.
flutter:
fonts:
- family: Icons
fonts:
- asset: lib/icons.ttf
You can also reduce the size of your application by removing support for flutter
material icons from your pubspec.yaml
.
flutter:
uses-material-design: false # or remove the line
The Icon Fonts generator may also have the following keys:
- import_path: The path that leads to the directory to get the
.svg
files to generate a webfont from. Defaults toicons
. - export_path: The path that leads to the file that is being generated.
Defaults to
lib/icons.g.dart
. - font_export_path: The path that leads to the
.ttf
file that is being generated. Defaults tolib/icons.ttf
. - export_encoding: The encoding used for writing the
.dart
files. Defaults toutf-8
. - encoding: The encoding used for reading the
.json
and.yaml
files. Defaults toutf-8
. - base_name: The name of the generated class. Defaults to
Icons
. - font_family: The name of the font family specified in the flutter section
of the
pubspec.yaml
. Defaults toIcons
. - base_code_point: The number to start listing icons from in the generated
font. This does not change the font generation, rather the dispayed
values themselves. Defaults to
0xf101
. - height: The height of the heighest icon. Learn more at the fantasticon options section.
- descent: The descent is usefull to fix the font baseline. Learn more at
the fantasticon options section. Defaults to
0
. - normalize: If the icons should be normalized by scaling them to the
height of the highest icon. Learn more at the fantasticon
options section. Defaults to
false
. - convert: If the icon names should be converted to
camel case. Disabling this option will prevent any changes
to be made to the icon names. Be certain to pass valid Dart names or the
generation will be likely to fail. Defaults to
true
. - package: The js package to run
npm install
oryarn install
with. Should be a valid path to a file with a package if running this generator from console. Defaults to package withfantasticon: ^1.2.3
. - yarn: If
yarn
should be used instead ofnpm
. Defaults tofalse
. - force: If the
package
should be installed forcefully. Otherwise, iffantasticon
executable is present, installation is ommited. Defaults tofalse
.
Contributing #
Contributions are welcomed!
Here is a curated list of how you can help:
- Report bugs and scenarios that are difficult to implement.
- Report parts of the documentation that are unclear.
- Fix typos/grammar mistakes.
- Update the documentation / add examples.
- Implement new features by making a pull-request.
FAQ #
Why another project when all of these generators already exist? #
While there are many different projects with the same goal of generating Dart code, there is none of them, that feature all mainly used generators in the same package, codebase, unified usage and resulting code.
That's why this is an attempt to make things easier, more convenient and better quality for the end user.
Is it safe to use in production? #
Yes, but with caution. Some use-cases may not be as simple as they could be.
But overall, you should be able to use these generators without any trouble.
Will a new generators be added over time? #
Of course they will!
Leave your suggestions at the official issue tracker.