diff --git a/.fvm/fvm_config.json b/.fvm/fvm_config.json deleted file mode 100644 index b8e6b4f..0000000 --- a/.fvm/fvm_config.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "flutterSdkVersion": "2.8.1", - "flavors": {} -} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 08dccd0..da1632e 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,21 @@ # Changelog +## [6.0.0] - 2022-10-04 +- Added the ability to specify simple fields in a more compact way, inline. + +Example: id and id2, name and name2 are equivalent notations +```yaml +ExampleModel: + properties: + id: string + id2: + type: string + required: true + name: string? + name2: + type: string + required: false +``` + ## [5.9.0] - 2022-03-29 - *POTENTIALLY BREAKING CHANGE*: By default, fields with a default value will now accept 'null' to use their default value - Add options to control whether fields with default value accepts 'null' or not diff --git a/README.md b/README.md index b04c1cd..2d839af 100755 --- a/README.md +++ b/README.md @@ -85,7 +85,7 @@ UserModel: type: int ignore_equality: true include: - type: string + type: String ``` ## explicit_to_json @@ -174,7 +174,7 @@ UserModel: type: int default_value: 1 name: - type: string + type: String required: true default_value: "'an example quoted string'" ``` @@ -204,7 +204,7 @@ UserModel: type: int default_value: 1 name: - type: string + type: String required: true default_value: "'an example quoted string'" ``` @@ -219,7 +219,7 @@ UserModel: type: int default_value: 1 name: - type: string + type: String required: true default_value: "'an example quoted string'" disallow_null: true @@ -259,7 +259,20 @@ UserDetails: extends: UserModel properties: name: - type: string + type: String +``` + +## Builtin types +The following framework types descriptors are known out of the box: +``` +string/String +int/integer +bool/boolean +double +date/datetime +dynamic/object/any +array +map ``` ## Default setup @@ -275,7 +288,7 @@ UserModel: id: type: int name: - type: string + type: String salary: type: double something: @@ -286,7 +299,7 @@ UserModel: roles: type: array items: - type: string + type: String birthday: type: date addresses: @@ -299,19 +312,19 @@ UserModel: key: String value: Address securityRole: - type: string + type: String jsonKey: securityIndicator dynamicField: type: dynamic includeIfNullField: include_if_null: false #If this field is null, this field will not be added to your json object (used for PATCH models) - type: string + type: String ignoreField: ignore: false #this field will not be final, and not be used in the json parsing - type: string + type: String mutableField: non_final: true #Field will not be marked final - type: string + type: String changedAt: type: datetime idToAddressList: @@ -324,7 +337,7 @@ Address: path: webservice/user #Can also be package:... and/or end with the actual file (.dart) properties: street: - type: string + type: String #Custom base_directory CustomBaseDirectoryObject: @@ -332,7 +345,7 @@ CustomBaseDirectoryObject: path: webservice properties: path: - type: string + type: String #Custom json converter. Use with converters property on models DateTimeConverter: @@ -341,6 +354,25 @@ DateTimeConverter: ``` +## Inline types (since 6.0.0) + +In some cases, writing the full specification for simple fields is very verbose. Since 6.0.0 it is possible to write simple fields inline, without nesting below the field name: + +```yaml +UserModel: + properties: + id: int + name: String + age: int + is_active: bool? + created_at: DateTime + roles: List + customProperties: Map? +``` + +Currently all basic types are supported, simple Lists and Maps (no nested types, no nullable generic parameters) as well as references to other objects. +Items post-fixed with `?` will be marked optional. + ## Enum support Add enums with custom values diff --git a/example/.fvm/fvm_config.json b/example/.fvm/fvm_config.json deleted file mode 100644 index 7f3f79f..0000000 --- a/example/.fvm/fvm_config.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "flutterSdkVersion": "2.10.3", - "flavors": {} -} \ No newline at end of file diff --git a/example/lib/model/ogm.dart b/example/lib/model/ogm.dart index 3390b63..91184e7 100644 --- a/example/lib/model/ogm.dart +++ b/example/lib/model/ogm.dart @@ -7,8 +7,6 @@ part 'ogm.g.dart'; @JsonSerializable(explicitToJson: true) @DateTimeConverter() class OGM { - @JsonKey(name: 'structuredMessage', required: true, includeIfNull: false) - final String structuredMessage; @JsonKey(name: 'beneficiary', required: true, includeIfNull: false) final String beneficiary; @JsonKey(name: 'beneficiaryIBAN', required: true, includeIfNull: false) @@ -19,6 +17,10 @@ class OGM { final String someThing; @JsonKey(name: 'some_ThinG_huGE', required: true, includeIfNull: false) final String someThinGHuGE; + @JsonKey(name: 'simpleFields', required: true) + final List simpleFields; + @JsonKey(name: 'structuredMessage') + final String? structuredMessage; @JsonKey(name: 'securityIndicator', includeIfNull: false) final String? securityRole; @JsonKey(name: 'mutableProperty', includeIfNull: false) @@ -27,18 +29,22 @@ class OGM { final DateTime? dateChange; @JsonKey(name: 'fields', includeIfNull: false) final List>? fields; + @JsonKey(name: 'simpleMap') + final Map? simpleMap; OGM({ - required this.structuredMessage, required this.beneficiary, required this.beneficiaryIBAN, required this.testTest, required this.someThing, required this.someThinGHuGE, + required this.simpleFields, + this.structuredMessage, this.securityRole, this.mutableProperty, this.dateChange, this.fields, + this.simpleMap, }); factory OGM.fromJson(Map json) => _$OGMFromJson(json); @@ -50,42 +56,48 @@ class OGM { identical(this, other) || other is OGM && runtimeType == other.runtimeType && - structuredMessage == other.structuredMessage && beneficiary == other.beneficiary && beneficiaryIBAN == other.beneficiaryIBAN && testTest == other.testTest && someThing == other.someThing && someThinGHuGE == other.someThinGHuGE && + simpleFields == other.simpleFields && + structuredMessage == other.structuredMessage && securityRole == other.securityRole && mutableProperty == other.mutableProperty && dateChange == other.dateChange && - fields == other.fields; + fields == other.fields && + simpleMap == other.simpleMap; @override int get hashCode => - structuredMessage.hashCode ^ beneficiary.hashCode ^ beneficiaryIBAN.hashCode ^ testTest.hashCode ^ someThing.hashCode ^ someThinGHuGE.hashCode ^ + simpleFields.hashCode ^ + structuredMessage.hashCode ^ securityRole.hashCode ^ mutableProperty.hashCode ^ dateChange.hashCode ^ - fields.hashCode; + fields.hashCode ^ + simpleMap.hashCode; @override String toString() => 'OGM{' - 'structuredMessage: $structuredMessage, ' 'beneficiary: $beneficiary, ' 'beneficiaryIBAN: $beneficiaryIBAN, ' 'testTest: $testTest, ' 'someThing: $someThing, ' 'someThinGHuGE: $someThinGHuGE, ' + 'simpleFields: $simpleFields, ' + 'structuredMessage: $structuredMessage, ' 'securityRole: $securityRole, ' 'mutableProperty: $mutableProperty, ' 'dateChange: $dateChange, ' - 'fields: $fields' + 'fields: $fields, ' + 'simpleMap: $simpleMap' '}'; } diff --git a/example/lib/model/ogm.g.dart b/example/lib/model/ogm.g.dart index 919da5e..dfd9401 100644 --- a/example/lib/model/ogm.g.dart +++ b/example/lib/model/ogm.g.dart @@ -10,21 +10,24 @@ OGM _$OGMFromJson(Map json) { $checkKeys( json, requiredKeys: const [ - 'structuredMessage', 'beneficiary', 'beneficiaryIBAN', 'test_Test', 'some_Thing', - 'some_ThinG_huGE' + 'some_ThinG_huGE', + 'simpleFields' ], ); return OGM( - structuredMessage: json['structuredMessage'] as String, beneficiary: json['beneficiary'] as String, beneficiaryIBAN: json['beneficiaryIBAN'] as String, testTest: json['test_Test'] as String, someThing: json['some_Thing'] as String, someThinGHuGE: json['some_ThinG_huGE'] as String, + simpleFields: (json['simpleFields'] as List) + .map((e) => Testing.fromJson(e as Map)) + .toList(), + structuredMessage: json['structuredMessage'] as String?, securityRole: json['securityIndicator'] as String?, mutableProperty: json['mutableProperty'] as String?, dateChange: json['dateChange'] == null @@ -35,17 +38,21 @@ OGM _$OGMFromJson(Map json) { .map((e) => Testing.fromJson(e as Map)) .toList()) .toList(), + simpleMap: (json['simpleMap'] as Map?)?.map( + (k, e) => MapEntry(k, Testing.fromJson(e as Map)), + ), ); } Map _$OGMToJson(OGM instance) { final val = { - 'structuredMessage': instance.structuredMessage, 'beneficiary': instance.beneficiary, 'beneficiaryIBAN': instance.beneficiaryIBAN, 'test_Test': instance.testTest, 'some_Thing': instance.someThing, 'some_ThinG_huGE': instance.someThinGHuGE, + 'simpleFields': instance.simpleFields.map((e) => e.toJson()).toList(), + 'structuredMessage': instance.structuredMessage, }; void writeNotNull(String key, dynamic value) { @@ -59,5 +66,6 @@ Map _$OGMToJson(OGM instance) { writeNotNull('dateChange', instance.dateChange?.toIso8601String()); writeNotNull('fields', instance.fields?.map((e) => e.map((e) => e.toJson()).toList()).toList()); + val['simpleMap'] = instance.simpleMap?.map((k, e) => MapEntry(k, e.toJson())); return val; } diff --git a/example/lib/model/user/profile/admin_profile_data.dart b/example/lib/model/user/profile/admin_profile_data.dart index 05db076..7b125e7 100644 --- a/example/lib/model/user/profile/admin_profile_data.dart +++ b/example/lib/model/user/profile/admin_profile_data.dart @@ -7,10 +7,10 @@ import 'package:model_generator_example/model/user/testing.dart'; part 'admin_profile_data.g.dart'; -@JsonSerializable() +@JsonSerializable(explicitToJson: true) @immutable class AdminProfileData extends UserProfileDataExtended { - @JsonKey(name: 'privileges', required: true) + @JsonKey(name: 'privileges', required: true, includeIfNull: false) final String privileges; const AdminProfileData({ @@ -76,3 +76,17 @@ class AdminProfileData extends UserProfileDataExtended { 'personsById: $personsById' '}'; } + +AdminProfileData deserializeAdminProfileData(Map json) => + AdminProfileData.fromJson(json); + +Map serializeAdminProfileData(AdminProfileData object) => + object.toJson(); + +List deserializeAdminProfileDataList( + List> jsonList) => + jsonList.map((json) => AdminProfileData.fromJson(json)).toList(); + +List> serializeAdminProfileDataList( + List objects) => + objects.map((object) => object.toJson()).toList(); diff --git a/example/lib/model/user/profile/admin_profile_data.g.dart b/example/lib/model/user/profile/admin_profile_data.g.dart index 9ecb394..d35092c 100644 --- a/example/lib/model/user/profile/admin_profile_data.g.dart +++ b/example/lib/model/user/profile/admin_profile_data.g.dart @@ -7,17 +7,20 @@ part of 'admin_profile_data.dart'; // ************************************************************************** AdminProfileData _$AdminProfileDataFromJson(Map json) { - $checkKeys(json, requiredKeys: const [ - 'firstName', - 'lastName', - 'standardLanguage', - 'mainAccountNumber', - 'legalEmail', - 'phones', - 'legalAddress', - 'additionalField', - 'privileges' - ]); + $checkKeys( + json, + requiredKeys: const [ + 'firstName', + 'lastName', + 'standardLanguage', + 'mainAccountNumber', + 'legalEmail', + 'phones', + 'legalAddress', + 'additionalField', + 'privileges' + ], + ); return AdminProfileData( privileges: json['privileges'] as String, additionalField: json['additionalField'] as String, @@ -49,8 +52,8 @@ Map _$AdminProfileDataToJson(AdminProfileData instance) { 'standardLanguage': instance.standardLanguage, 'mainAccountNumber': instance.mainAccountNumber, 'legalEmail': instance.legalEmail, - 'phones': instance.phones, - 'legalAddress': instance.legalAddress, + 'phones': instance.phones.toJson(), + 'legalAddress': instance.legalAddress.toJson(), }; void writeNotNull(String key, dynamic value) { @@ -60,9 +63,10 @@ Map _$AdminProfileDataToJson(AdminProfileData instance) { } writeNotNull('offTrack', instance.offTrack); - val['onTrack'] = instance.onTrack; - val['persons'] = instance.persons; - val['personsById'] = instance.personsById; + val['onTrack'] = instance.onTrack?.map((e) => e.toJson()).toList(); + writeNotNull('persons', instance.persons?.map((e) => e.toJson()).toList()); + writeNotNull('personsById', + instance.personsById?.map((k, e) => MapEntry(k, e.toJson()))); val['additionalField'] = instance.additionalField; val['privileges'] = instance.privileges; return val; diff --git a/example/lib/model/user/profile/user_profile_data_extended.dart b/example/lib/model/user/profile/user_profile_data_extended.dart index 2fbea51..1865c3d 100644 --- a/example/lib/model/user/profile/user_profile_data_extended.dart +++ b/example/lib/model/user/profile/user_profile_data_extended.dart @@ -7,10 +7,10 @@ import 'package:model_generator_example/model/user/testing.dart'; part 'user_profile_data_extended.g.dart'; -@JsonSerializable() +@JsonSerializable(explicitToJson: true) @immutable class UserProfileDataExtended extends UserProfileData { - @JsonKey(name: 'additionalField', required: true) + @JsonKey(name: 'additionalField', required: true, includeIfNull: false) final String additionalField; const UserProfileDataExtended({ @@ -73,3 +73,19 @@ class UserProfileDataExtended extends UserProfileData { 'personsById: $personsById' '}'; } + +UserProfileDataExtended deserializeUserProfileDataExtended( + Map json) => + UserProfileDataExtended.fromJson(json); + +Map serializeUserProfileDataExtended( + UserProfileDataExtended object) => + object.toJson(); + +List deserializeUserProfileDataExtendedList( + List> jsonList) => + jsonList.map((json) => UserProfileDataExtended.fromJson(json)).toList(); + +List> serializeUserProfileDataExtendedList( + List objects) => + objects.map((object) => object.toJson()).toList(); diff --git a/example/lib/model/user/profile/user_profile_data_extended.g.dart b/example/lib/model/user/profile/user_profile_data_extended.g.dart index 494a45d..2619837 100644 --- a/example/lib/model/user/profile/user_profile_data_extended.g.dart +++ b/example/lib/model/user/profile/user_profile_data_extended.g.dart @@ -8,16 +8,19 @@ part of 'user_profile_data_extended.dart'; UserProfileDataExtended _$UserProfileDataExtendedFromJson( Map json) { - $checkKeys(json, requiredKeys: const [ - 'firstName', - 'lastName', - 'standardLanguage', - 'mainAccountNumber', - 'legalEmail', - 'phones', - 'legalAddress', - 'additionalField' - ]); + $checkKeys( + json, + requiredKeys: const [ + 'firstName', + 'lastName', + 'standardLanguage', + 'mainAccountNumber', + 'legalEmail', + 'phones', + 'legalAddress', + 'additionalField' + ], + ); return UserProfileDataExtended( additionalField: json['additionalField'] as String, firstName: json['firstName'] as String, @@ -49,8 +52,8 @@ Map _$UserProfileDataExtendedToJson( 'standardLanguage': instance.standardLanguage, 'mainAccountNumber': instance.mainAccountNumber, 'legalEmail': instance.legalEmail, - 'phones': instance.phones, - 'legalAddress': instance.legalAddress, + 'phones': instance.phones.toJson(), + 'legalAddress': instance.legalAddress.toJson(), }; void writeNotNull(String key, dynamic value) { @@ -60,9 +63,10 @@ Map _$UserProfileDataExtendedToJson( } writeNotNull('offTrack', instance.offTrack); - val['onTrack'] = instance.onTrack; - val['persons'] = instance.persons; - val['personsById'] = instance.personsById; + val['onTrack'] = instance.onTrack?.map((e) => e.toJson()).toList(); + writeNotNull('persons', instance.persons?.map((e) => e.toJson()).toList()); + writeNotNull('personsById', + instance.personsById?.map((k, e) => MapEntry(k, e.toJson()))); val['additionalField'] = instance.additionalField; return val; } diff --git a/example/lib/model/user/project/project.dart b/example/lib/model/user/project/project.dart index 38d3afd..d706701 100644 --- a/example/lib/model/user/project/project.dart +++ b/example/lib/model/user/project/project.dart @@ -9,7 +9,7 @@ class Project { @JsonKey( name: 'name', required: false, - disallowNullValue: true, + disallowNullValue: false, includeIfNull: false) final String name; @JsonKey(name: 'cost', includeIfNull: false) diff --git a/example/lib/model/user/project/project.g.dart b/example/lib/model/user/project/project.g.dart index 1af4cf3..7a23d95 100644 --- a/example/lib/model/user/project/project.g.dart +++ b/example/lib/model/user/project/project.g.dart @@ -6,16 +6,10 @@ part of 'project.dart'; // JsonSerializableGenerator // ************************************************************************** -Project _$ProjectFromJson(Map json) { - $checkKeys( - json, - disallowNullValues: const ['name'], - ); - return Project( - name: json['name'] as String? ?? 'test', - cost: (json['cost'] as num?)?.toDouble() ?? 0.2, - ); -} +Project _$ProjectFromJson(Map json) => Project( + name: json['name'] as String? ?? 'test', + cost: (json['cost'] as num?)?.toDouble() ?? 0.2, + ); Map _$ProjectToJson(Project instance) { final val = { diff --git a/example/model_generator/config.yaml b/example/model_generator/config.yaml index 6ecf475..cc0b19c 100644 --- a/example/model_generator/config.yaml +++ b/example/model_generator/config.yaml @@ -7,9 +7,7 @@ OGM: extra_imports: - properties: - structuredMessage: - required: true - type: string + structuredMessage: string? beneficiary: required: true type: string @@ -37,6 +35,8 @@ OGM: type: array items: type: List + simpleFields: List + simpleMap: Map? Testing: path: user diff --git a/lib/config/yml_generator_config.dart b/lib/config/yml_generator_config.dart index 7bcbd69..82902e7 100644 --- a/lib/config/yml_generator_config.dart +++ b/lib/config/yml_generator_config.dart @@ -128,11 +128,14 @@ class YmlGeneratorConfig { : pubspecConfig.disallowNullForDefaults; final fields = []; properties.forEach((propertyKey, propertyValue) { - if (propertyValue is! YamlMap) { + if (propertyValue is YamlMap) { + fields.add(getField(propertyKey, propertyValue, + disallowNullForDefaults: disallowNullForDefaults)); + } else if (propertyValue is String) { + fields.add(getSimpleField(name: propertyKey, value: propertyValue)); + } else { throw Exception('$propertyKey should be an object'); } - fields.add(getField(propertyKey, propertyValue, - disallowNullForDefaults: disallowNullForDefaults)); }); final mappedConverters = converters?.map((element) => element.toString()).toList(); @@ -177,7 +180,7 @@ class YmlGeneratorConfig { final description = property.containsKey('description') ? property['description']!.toString() : null; - final type = property['type']; + final type = property['type'] as String?; final skipEquality = property['ignore_equality'] == true; final defaultValue = property['default_value']?.toString(); final disallowNull = property.containsKey('disallow_null') @@ -188,23 +191,26 @@ class YmlGeneratorConfig { if (type == null) { throw Exception('$name has no defined type'); } - if (type == 'object' || type == 'dynamic' || type == 'any') { + final lowerType = type.toLowerCase(); + if (lowerType == 'object' || + lowerType == 'dynamic' || + lowerType == 'any') { itemType = DynamicType(); - } else if (type == 'bool' || type == 'boolean') { + } else if (type == 'bool' || lowerType == 'boolean') { itemType = BooleanType(); - } else if (type == 'string' || type == 'String') { + } else if (lowerType == 'string') { itemType = StringType(); - } else if (type == 'date' || type == 'datetime') { + } else if (lowerType == 'date' || lowerType == 'datetime') { itemType = DateTimeType(); - } else if (type == 'double') { + } else if (lowerType == 'double') { itemType = DoubleType(); } else if (type == 'int' || type == 'integer') { itemType = IntegerType(); - } else if (type == 'array') { + } else if (lowerType == 'array') { final items = property['items']; final arrayType = items['type']; itemType = ArrayType(_makeGenericName(arrayType)); - } else if (type == 'map') { + } else if (lowerType == 'map') { final items = property['items']; final keyType = items['key']; final valueType = items['value']; @@ -237,20 +243,38 @@ class YmlGeneratorConfig { } } + Field getSimpleField({required String name, required String value}) { + final optional = value.endsWith('?'); + final typeString = optional ? value.substring(0, value.length - 1) : value; + + final type = _parseSimpleType(typeString); + + return Field( + name: name, + type: type, + isRequired: !optional, + ignore: false, + includeIfNull: true, + nonFinal: false, + ignoreEquality: false, + ); + } + String _makeGenericName(String typeName) { - if (typeName == 'string' || typeName == 'String') { + final lowerType = typeName.toLowerCase(); + if (lowerType == 'string') { return 'String'; - } else if (typeName == 'bool' || typeName == 'boolean') { + } else if (lowerType == 'bool' || lowerType == 'boolean') { return 'bool'; - } else if (typeName == 'double') { + } else if (lowerType == 'double') { return 'double'; - } else if (typeName == 'date' || typeName == 'datetime') { + } else if (lowerType == 'date' || lowerType == 'datetime') { return 'DateTime'; - } else if (typeName == 'int' || typeName == 'integer') { + } else if (lowerType == 'int' || lowerType == 'integer') { return 'int'; - } else if (typeName == 'object' || - typeName == 'dynamic' || - typeName == 'any') { + } else if (lowerType == 'object' || + lowerType == 'dynamic' || + lowerType == 'any') { return 'dynamic'; } else { return typeName; @@ -342,4 +366,35 @@ class YmlGeneratorConfig { 'Could not generate all models. `$type` is not added to the config file, but is extended. These types are known: ${names.join(',')}'); } } + + ItemType _parseSimpleType(String type) { + final listRegex = RegExp(r'^\s*[Ll]ist<\s*([a-zA-Z_0-9]*)\s*>\s*$'); + final mapRegex = + RegExp(r'^\s*[Mm]ap<([a-zA-Z_0-9]*)\s*,\s*([a-zA-Z_0-9]*)\s*>\s*$'); + + final lowerType = type.toLowerCase(); + + if (lowerType == 'object' || lowerType == 'dynamic' || lowerType == 'any') { + return DynamicType(); + } else if (lowerType == 'bool' || lowerType == 'boolean') { + return BooleanType(); + } else if (lowerType == 'string') { + return StringType(); + } else if (lowerType == 'date' || lowerType == 'datetime') { + return DateTimeType(); + } else if (lowerType == 'double') { + return DoubleType(); + } else if (lowerType == 'int' || lowerType == 'integer') { + return IntegerType(); + } else if (listRegex.hasMatch(type)) { + final arrayType = listRegex.firstMatch(type)!.group(1)!; + return ArrayType(_makeGenericName(arrayType)); + } else if (mapRegex.hasMatch(type)) { + final match = mapRegex.firstMatch(type)!; + return MapType( + key: _makeGenericName(match.group(1)!), + valueName: _makeGenericName(match.group(2)!)); + } + return ObjectType(type); + } } diff --git a/pubspec.yaml b/pubspec.yaml index 969eb09..7fd436a 100755 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,10 +1,10 @@ name: model_generator description: Dart tool to automaticly generate models from a yml file to speed up your development flow. -version: 5.9.0 +version: 6.0.0 homepage: https://github.com/icapps/flutter-model-generator environment: - sdk: ">=2.12.0 <3.0.0" + sdk: ">=2.17.0 <3.0.0" dependencies: args: ^2.3.0 @@ -14,5 +14,5 @@ dependencies: yaml: ^3.1.0 dev_dependencies: - test: 1.19.5 - lints: ^1.0.1 + test: 1.21.6 + lints: ^2.0.0 diff --git a/test/writer/model_reader_test.dart b/test/writer/model_reader_test.dart new file mode 100644 index 0000000..0a60d87 --- /dev/null +++ b/test/writer/model_reader_test.dart @@ -0,0 +1,129 @@ +import 'package:model_generator/config/pubspec_config.dart'; +import 'package:model_generator/config/yml_generator_config.dart'; +import 'package:model_generator/model/field.dart'; +import 'package:model_generator/model/item_type/array_type.dart'; +import 'package:model_generator/model/item_type/boolean_type.dart'; +import 'package:model_generator/model/item_type/date_time_type.dart'; +import 'package:model_generator/model/item_type/double_type.dart'; +import 'package:model_generator/model/item_type/dynamic_type.dart'; +import 'package:model_generator/model/item_type/integer_type.dart'; +import 'package:model_generator/model/item_type/map_type.dart'; +import 'package:model_generator/model/item_type/object_type.dart'; +import 'package:model_generator/model/item_type/string_type.dart'; +import 'package:model_generator/model/model/object_model.dart'; +import 'package:test/test.dart'; + +void main() { + group('ModelReaderTest', () { + test('Test simple basic fields', () { + final models = YmlGeneratorConfig(PubspecConfig("name: test"), """ +TestModel: + properties: + simpleString: string + nullableString: string? + simpleInt: int + simpleBool: bool + simpleDouble: double + simpleDynamic: dynamic + simpleDateTime: datetime? +""").models; + + expect(models.length, 1); + final model = models.first; + expect(model is ObjectModel, true); + model as ObjectModel; + + final simpleString = model.fields.getByName("simpleString"); + final nullableString = model.fields.getByName("nullableString"); + final simpleInt = model.fields.getByName("simpleInt"); + final simpleBool = model.fields.getByName("simpleBool"); + final simpleDouble = model.fields.getByName("simpleDouble"); + final simpleDynamic = model.fields.getByName("simpleDynamic"); + final simpleDateTime = model.fields.getByName("simpleDateTime"); + + expect(simpleString.type, isA()); + expect(simpleString.isRequired, true); + + expect(nullableString.type, isA()); + expect(nullableString.isRequired, false); + + expect(simpleInt.type, isA()); + expect(simpleInt.isRequired, true); + + expect(simpleBool.type, isA()); + expect(simpleBool.isRequired, true); + + expect(simpleDouble.type, isA()); + expect(simpleDouble.isRequired, true); + + expect(simpleDynamic.type, isA()); + expect(simpleDynamic.isRequired, true); + + expect(simpleDateTime.type, isA()); + expect(simpleDateTime.isRequired, false); + }); + test('Test simple generic fields', () { + final models = YmlGeneratorConfig(PubspecConfig("name: test"), """ +TestModel: + properties: + simpleStringList: List + nullableStringList: List? + simpleMap: Map +""").models; + + expect(models.length, 1); + final model = models.first; + expect(model is ObjectModel, true); + model as ObjectModel; + + final simpleStringList = model.fields.getByName("simpleStringList"); + final nullableStringList = model.fields.getByName("nullableStringList"); + final simpleMap = model.fields.getByName("simpleMap"); + + expect(simpleStringList.type, isA()); + expect(simpleStringList.isRequired, true); + + expect(nullableStringList.type, isA()); + expect(nullableStringList.isRequired, false); + + expect(simpleMap.type, isA()); + expect(simpleMap.isRequired, true); + }); + test('Test simple object reference fields', () { + final models = YmlGeneratorConfig(PubspecConfig("name: test"), """ +TestModel: + properties: + simpleRef: TestModel2 + listRef: List? + nullableRef: TestModel2? +TestModel2: + properties: + simpleMap: Map +""").models; + + expect(models.length, 2); + final model = models.firstWhere((element) => element.name == 'TestModel'); + expect(model is ObjectModel, true); + model as ObjectModel; + + final simpleRef = model.fields.getByName("simpleRef"); + final listRef = model.fields.getByName("listRef"); + final nullableRef = model.fields.getByName("nullableRef"); + + expect(simpleRef.type, isA()); + expect(simpleRef.isRequired, true); + + expect(listRef.type, isA()); + expect(listRef.isRequired, false); + + expect(nullableRef.type, isA()); + expect(nullableRef.isRequired, false); + }); + }); +} + +extension _ListHelper on List { + Field getByName(String name) { + return firstWhere((element) => element.name == name); + } +}