diff --git a/packages/dynamite/dynamite/lib/src/builder/generate_schemas.dart b/packages/dynamite/dynamite/lib/src/builder/generate_schemas.dart index 17a6c46f..604fea9e 100644 --- a/packages/dynamite/dynamite/lib/src/builder/generate_schemas.dart +++ b/packages/dynamite/dynamite/lib/src/builder/generate_schemas.dart @@ -3,6 +3,7 @@ import 'package:dynamite/src/builder/resolve_type.dart'; import 'package:dynamite/src/builder/state.dart'; import 'package:dynamite/src/helpers/dart_helpers.dart'; import 'package:dynamite/src/models/openapi.dart' as openapi; +import 'package:dynamite/src/models/type_result.dart'; Iterable generateSchemas( final openapi.OpenAPI spec, @@ -11,13 +12,21 @@ Iterable generateSchemas( if (spec.components?.schemas != null) { for (final schema in spec.components!.schemas!.entries) { final identifier = toDartName(schema.key, uppercaseFirstCharacter: true); - - resolveType( + final result = resolveType( spec, state, identifier, schema.value, ); + + // TypeDefs should only be generated for top level schemas. + if (result is TypeResultBase || result.isTypeDef) { + yield TypeDef( + (final b) => b + ..name = identifier + ..definition = refer(result.name), + ); + } } } diff --git a/packages/dynamite/dynamite/lib/src/builder/resolve_type.dart b/packages/dynamite/dynamite/lib/src/builder/resolve_type.dart index 607f5ad6..6ba67236 100644 --- a/packages/dynamite/dynamite/lib/src/builder/resolve_type.dart +++ b/packages/dynamite/dynamite/lib/src/builder/resolve_type.dart @@ -22,13 +22,15 @@ TypeResult resolveType( } if (schema.ref != null) { final name = schema.ref!.split('/').last; - result = resolveType( + final subResult = resolveType( spec, state, name, spec.components!.schemas![name]!, nullable: nullable, ); + + result = subResult.asTypeDef; } else if (schema.allOf != null) { result = resolveAllOf( spec, diff --git a/packages/dynamite/dynamite/lib/src/models/type_result/base.dart b/packages/dynamite/dynamite/lib/src/models/type_result/base.dart index aa58e38c..eba4205f 100644 --- a/packages/dynamite/dynamite/lib/src/models/type_result/base.dart +++ b/packages/dynamite/dynamite/lib/src/models/type_result/base.dart @@ -5,6 +5,7 @@ class TypeResultBase extends TypeResult { TypeResultBase( super.className, { super.nullable, + super.isTypeDef, }); @override diff --git a/packages/dynamite/dynamite/lib/src/models/type_result/enum.dart b/packages/dynamite/dynamite/lib/src/models/type_result/enum.dart index 805f9253..9a86f29f 100644 --- a/packages/dynamite/dynamite/lib/src/models/type_result/enum.dart +++ b/packages/dynamite/dynamite/lib/src/models/type_result/enum.dart @@ -6,6 +6,7 @@ class TypeResultEnum extends TypeResult { super.className, this.subType, { super.nullable, + super.isTypeDef, }); final TypeResult subType; diff --git a/packages/dynamite/dynamite/lib/src/models/type_result/list.dart b/packages/dynamite/dynamite/lib/src/models/type_result/list.dart index c56f2731..69a8e9ed 100644 --- a/packages/dynamite/dynamite/lib/src/models/type_result/list.dart +++ b/packages/dynamite/dynamite/lib/src/models/type_result/list.dart @@ -6,6 +6,7 @@ class TypeResultList extends TypeResult { super.className, final TypeResult subType, { super.nullable, + super.isTypeDef, }) : super(generics: [subType]); TypeResult get subType => generics.first; diff --git a/packages/dynamite/dynamite/lib/src/models/type_result/map.dart b/packages/dynamite/dynamite/lib/src/models/type_result/map.dart index ce18b15b..73646080 100644 --- a/packages/dynamite/dynamite/lib/src/models/type_result/map.dart +++ b/packages/dynamite/dynamite/lib/src/models/type_result/map.dart @@ -6,6 +6,7 @@ class TypeResultMap extends TypeResult { super.className, final TypeResult subType, { super.nullable, + super.isTypeDef, }) : super(generics: [TypeResultBase('String'), subType]); TypeResult get subType => generics[1]; diff --git a/packages/dynamite/dynamite/lib/src/models/type_result/object.dart b/packages/dynamite/dynamite/lib/src/models/type_result/object.dart index 830f91a7..e3d28c57 100644 --- a/packages/dynamite/dynamite/lib/src/models/type_result/object.dart +++ b/packages/dynamite/dynamite/lib/src/models/type_result/object.dart @@ -8,6 +8,7 @@ class TypeResultObject extends TypeResult { super.className, { super.generics, super.nullable, + super.isTypeDef, }) : assert( className != 'JsonObject' && className != 'Object' && className != 'dynamic', 'Use TypeResultBase instead', diff --git a/packages/dynamite/dynamite/lib/src/models/type_result/type_result.dart b/packages/dynamite/dynamite/lib/src/models/type_result/type_result.dart index 46eb94ac..c7f96eee 100644 --- a/packages/dynamite/dynamite/lib/src/models/type_result/type_result.dart +++ b/packages/dynamite/dynamite/lib/src/models/type_result/type_result.dart @@ -13,6 +13,7 @@ sealed class TypeResult { this.className, { this.generics = const [], this.nullable = false, + this.isTypeDef = false, }) : assert(!className.contains('<'), 'Specify generics in the generics parameter.'), assert(!className.contains('?'), 'Nullability should not be specified in the type.'); @@ -20,6 +21,9 @@ sealed class TypeResult { final List generics; final bool nullable; + /// Whether this type should be represented as a typedef. + final bool isTypeDef; + String get name { if (generics.isNotEmpty) { final buffer = StringBuffer('$className<') @@ -44,6 +48,10 @@ sealed class TypeResult { } Iterable get serializers sync* { + if (isTypeDef) { + return; + } + for (final class_ in generics) { yield* class_.serializers; } @@ -104,6 +112,44 @@ sealed class TypeResult { // ignore: avoid_returning_this TypeResult get dartType => this; + /// Returns `this` with a `true` value for [isTypeDef]. + TypeResult get asTypeDef { + final $this = this; + + // We need to preserve the original runtime type. + return switch ($this) { + TypeResultBase() => TypeResultBase( + className, + nullable: nullable, + isTypeDef: true, + ), + TypeResultEnum() => TypeResultEnum( + className, + $this.subType, + nullable: nullable, + isTypeDef: true, + ), + TypeResultList() => TypeResultList( + className, + $this.subType, + nullable: nullable, + isTypeDef: true, + ), + TypeResultMap() => TypeResultMap( + className, + $this.subType, + nullable: nullable, + isTypeDef: true, + ), + TypeResultObject() => TypeResultObject( + className, + generics: generics, + nullable: nullable, + isTypeDef: true, + ), + }; + } + @override bool operator ==(final Object other) => other is TypeResult && other.className == className && other.generics == generics; diff --git a/packages/dynamite/dynamite_end_to_end_test/lib/type_defs.openapi.dart b/packages/dynamite/dynamite_end_to_end_test/lib/type_defs.openapi.dart new file mode 100644 index 00000000..20cd4f8c --- /dev/null +++ b/packages/dynamite/dynamite_end_to_end_test/lib/type_defs.openapi.dart @@ -0,0 +1,170 @@ +// ignore_for_file: camel_case_types +// ignore_for_file: discarded_futures +// ignore_for_file: public_member_api_docs +// ignore_for_file: unreachable_switch_case + +import 'package:built_value/built_value.dart'; +import 'package:built_value/json_object.dart'; +import 'package:built_value/serializer.dart'; +import 'package:built_value/standard_json_plugin.dart'; +import 'package:collection/collection.dart'; +import 'package:dynamite_runtime/built_value.dart'; +import 'package:dynamite_runtime/http_client.dart'; + +part 'type_defs.openapi.g.dart'; + +class Client extends DynamiteClient { + Client( + super.baseURL, { + super.baseHeaders, + super.userAgent, + super.httpClient, + super.cookieJar, + }); + + Client.fromClient(final DynamiteClient client) + : super( + client.baseURL, + baseHeaders: client.baseHeaders, + httpClient: client.httpClient, + cookieJar: client.cookieJar, + authentications: client.authentications, + ); +} + +typedef TypeResultBase = int; + +typedef EmptySchema = JsonObject; + +typedef Redirect = Base; + +typedef RedirectBaseType = int; + +typedef RedirectEmptyType = JsonObject; + +@BuiltValue(instantiable: false) +abstract interface class BaseInterface { + String? get attribute; +} + +abstract class Base implements BaseInterface, Built { + factory Base([final void Function(BaseBuilder)? b]) = _$Base; + + const Base._(); + + factory Base.fromJson(final Map json) => _jsonSerializers.deserializeWith(serializer, json)!; + + Map toJson() => _jsonSerializers.serializeWith(serializer, this)! as Map; + + static Serializer get serializer => _$baseSerializer; +} + +@BuiltValue(instantiable: false) +abstract interface class NestedRedirectInterface { + Base? get redirect; + int? get redirectBaseType; + JsonObject? get redirectEmptyType; +} + +abstract class NestedRedirect implements NestedRedirectInterface, Built { + factory NestedRedirect([final void Function(NestedRedirectBuilder)? b]) = _$NestedRedirect; + + const NestedRedirect._(); + + factory NestedRedirect.fromJson(final Map json) => + _jsonSerializers.deserializeWith(serializer, json)!; + + Map toJson() => _jsonSerializers.serializeWith(serializer, this)! as Map; + + static Serializer get serializer => _$nestedRedirectSerializer; +} + +@BuiltValue(instantiable: false) +abstract interface class SomeOfRedirectInterface { + Base? get base; + int? get $int; + JsonObject? get jsonObject; +} + +abstract class SomeOfRedirect implements SomeOfRedirectInterface, Built { + factory SomeOfRedirect([final void Function(SomeOfRedirectBuilder)? b]) = _$SomeOfRedirect; + + const SomeOfRedirect._(); + + factory SomeOfRedirect.fromJson(final Map json) => + _jsonSerializers.deserializeWith(serializer, json)!; + + Map toJson() => _jsonSerializers.serializeWith(serializer, this)! as Map; + + @BuiltValueSerializer(custom: true) + static Serializer get serializer => _$SomeOfRedirectSerializer(); + + JsonObject get data; + @BuiltValueHook(finalizeBuilder: true) + static void _validate(final SomeOfRedirectBuilder b) { + // When this is rebuild from another builder + if (b._data == null) { + return; + } + + final match = [b._base, b._$int, b._jsonObject].singleWhereOrNull((final x) => x != null); + if (match == null) { + throw StateError("Need exactly one of 'base', '$int', 'jsonObject' for ${b._data}"); + } + } +} + +class _$SomeOfRedirectSerializer implements PrimitiveSerializer { + @override + final Iterable types = const [SomeOfRedirect, _$SomeOfRedirect]; + + @override + final String wireName = 'SomeOfRedirect'; + + @override + Object serialize( + final Serializers serializers, + final SomeOfRedirect object, { + final FullType specifiedType = FullType.unspecified, + }) => + object.data.value; + + @override + SomeOfRedirect deserialize( + final Serializers serializers, + final Object data, { + final FullType specifiedType = FullType.unspecified, + }) { + final result = SomeOfRedirectBuilder()..data = JsonObject(data); + try { + final value = _jsonSerializers.deserialize(data, specifiedType: const FullType(Base))! as Base; + result.base.replace(value); + } catch (_) {} + try { + final value = _jsonSerializers.deserialize(data, specifiedType: const FullType(int))! as int; + result.$int = value; + } catch (_) {} + try { + final value = _jsonSerializers.deserialize(data, specifiedType: const FullType(JsonObject))! as JsonObject; + result.jsonObject = value; + } catch (_) {} + return result.build(); + } +} + +// coverage:ignore-start +final Serializers _serializers = (Serializers().toBuilder() + ..addBuilderFactory(const FullType(Base), Base.new) + ..add(Base.serializer) + ..addBuilderFactory(const FullType(NestedRedirect), NestedRedirect.new) + ..add(NestedRedirect.serializer) + ..addBuilderFactory(const FullType(SomeOfRedirect), SomeOfRedirect.new) + ..add(SomeOfRedirect.serializer)) + .build(); + +final Serializers _jsonSerializers = (_serializers.toBuilder() + ..add(DynamiteDoubleSerializer()) + ..addPlugin(StandardJsonPlugin()) + ..addPlugin(const ContentStringPlugin())) + .build(); +// coverage:ignore-end diff --git a/packages/dynamite/dynamite_end_to_end_test/lib/type_defs.openapi.g.dart b/packages/dynamite/dynamite_end_to_end_test/lib/type_defs.openapi.g.dart new file mode 100644 index 00000000..87686cf1 --- /dev/null +++ b/packages/dynamite/dynamite_end_to_end_test/lib/type_defs.openapi.g.dart @@ -0,0 +1,456 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'type_defs.openapi.dart'; + +// ************************************************************************** +// BuiltValueGenerator +// ************************************************************************** + +Serializer _$baseSerializer = _$BaseSerializer(); +Serializer _$nestedRedirectSerializer = _$NestedRedirectSerializer(); + +class _$BaseSerializer implements StructuredSerializer { + @override + final Iterable types = const [Base, _$Base]; + @override + final String wireName = 'Base'; + + @override + Iterable serialize(Serializers serializers, Base object, {FullType specifiedType = FullType.unspecified}) { + final result = []; + Object? value; + value = object.attribute; + if (value != null) { + result + ..add('attribute') + ..add(serializers.serialize(value, specifiedType: const FullType(String))); + } + return result; + } + + @override + Base deserialize(Serializers serializers, Iterable serialized, + {FullType specifiedType = FullType.unspecified}) { + final result = BaseBuilder(); + + final iterator = serialized.iterator; + while (iterator.moveNext()) { + final key = iterator.current! as String; + iterator.moveNext(); + final Object? value = iterator.current; + switch (key) { + case 'attribute': + result.attribute = serializers.deserialize(value, specifiedType: const FullType(String)) as String?; + break; + } + } + + return result.build(); + } +} + +class _$NestedRedirectSerializer implements StructuredSerializer { + @override + final Iterable types = const [NestedRedirect, _$NestedRedirect]; + @override + final String wireName = 'NestedRedirect'; + + @override + Iterable serialize(Serializers serializers, NestedRedirect object, + {FullType specifiedType = FullType.unspecified}) { + final result = []; + Object? value; + value = object.redirect; + if (value != null) { + result + ..add('redirect') + ..add(serializers.serialize(value, specifiedType: const FullType(Base))); + } + value = object.redirectBaseType; + if (value != null) { + result + ..add('redirectBaseType') + ..add(serializers.serialize(value, specifiedType: const FullType(int))); + } + value = object.redirectEmptyType; + if (value != null) { + result + ..add('redirectEmptyType') + ..add(serializers.serialize(value, specifiedType: const FullType(JsonObject))); + } + return result; + } + + @override + NestedRedirect deserialize(Serializers serializers, Iterable serialized, + {FullType specifiedType = FullType.unspecified}) { + final result = NestedRedirectBuilder(); + + final iterator = serialized.iterator; + while (iterator.moveNext()) { + final key = iterator.current! as String; + iterator.moveNext(); + final Object? value = iterator.current; + switch (key) { + case 'redirect': + result.redirect.replace(serializers.deserialize(value, specifiedType: const FullType(Base))! as Base); + break; + case 'redirectBaseType': + result.redirectBaseType = serializers.deserialize(value, specifiedType: const FullType(int)) as int?; + break; + case 'redirectEmptyType': + result.redirectEmptyType = + serializers.deserialize(value, specifiedType: const FullType(JsonObject)) as JsonObject?; + break; + } + } + + return result.build(); + } +} + +abstract mixin class BaseInterfaceBuilder { + void replace(BaseInterface other); + void update(void Function(BaseInterfaceBuilder) updates); + String? get attribute; + set attribute(String? attribute); +} + +class _$Base extends Base { + @override + final String? attribute; + + factory _$Base([void Function(BaseBuilder)? updates]) => (BaseBuilder()..update(updates))._build(); + + _$Base._({this.attribute}) : super._(); + + @override + Base rebuild(void Function(BaseBuilder) updates) => (toBuilder()..update(updates)).build(); + + @override + BaseBuilder toBuilder() => BaseBuilder()..replace(this); + + @override + bool operator ==(Object other) { + if (identical(other, this)) return true; + return other is Base && attribute == other.attribute; + } + + @override + int get hashCode { + var _$hash = 0; + _$hash = $jc(_$hash, attribute.hashCode); + _$hash = $jf(_$hash); + return _$hash; + } + + @override + String toString() { + return (newBuiltValueToStringHelper(r'Base')..add('attribute', attribute)).toString(); + } +} + +class BaseBuilder implements Builder, BaseInterfaceBuilder { + _$Base? _$v; + + String? _attribute; + String? get attribute => _$this._attribute; + set attribute(covariant String? attribute) => _$this._attribute = attribute; + + BaseBuilder(); + + BaseBuilder get _$this { + final $v = _$v; + if ($v != null) { + _attribute = $v.attribute; + _$v = null; + } + return this; + } + + @override + void replace(covariant Base other) { + ArgumentError.checkNotNull(other, 'other'); + _$v = other as _$Base; + } + + @override + void update(void Function(BaseBuilder)? updates) { + if (updates != null) updates(this); + } + + @override + Base build() => _build(); + + _$Base _build() { + final _$result = _$v ?? _$Base._(attribute: attribute); + replace(_$result); + return _$result; + } +} + +abstract mixin class NestedRedirectInterfaceBuilder { + void replace(NestedRedirectInterface other); + void update(void Function(NestedRedirectInterfaceBuilder) updates); + BaseBuilder get redirect; + set redirect(BaseBuilder? redirect); + + int? get redirectBaseType; + set redirectBaseType(int? redirectBaseType); + + JsonObject? get redirectEmptyType; + set redirectEmptyType(JsonObject? redirectEmptyType); +} + +class _$NestedRedirect extends NestedRedirect { + @override + final Base? redirect; + @override + final int? redirectBaseType; + @override + final JsonObject? redirectEmptyType; + + factory _$NestedRedirect([void Function(NestedRedirectBuilder)? updates]) => + (NestedRedirectBuilder()..update(updates))._build(); + + _$NestedRedirect._({this.redirect, this.redirectBaseType, this.redirectEmptyType}) : super._(); + + @override + NestedRedirect rebuild(void Function(NestedRedirectBuilder) updates) => (toBuilder()..update(updates)).build(); + + @override + NestedRedirectBuilder toBuilder() => NestedRedirectBuilder()..replace(this); + + @override + bool operator ==(Object other) { + if (identical(other, this)) return true; + return other is NestedRedirect && + redirect == other.redirect && + redirectBaseType == other.redirectBaseType && + redirectEmptyType == other.redirectEmptyType; + } + + @override + int get hashCode { + var _$hash = 0; + _$hash = $jc(_$hash, redirect.hashCode); + _$hash = $jc(_$hash, redirectBaseType.hashCode); + _$hash = $jc(_$hash, redirectEmptyType.hashCode); + _$hash = $jf(_$hash); + return _$hash; + } + + @override + String toString() { + return (newBuiltValueToStringHelper(r'NestedRedirect') + ..add('redirect', redirect) + ..add('redirectBaseType', redirectBaseType) + ..add('redirectEmptyType', redirectEmptyType)) + .toString(); + } +} + +class NestedRedirectBuilder implements Builder, NestedRedirectInterfaceBuilder { + _$NestedRedirect? _$v; + + BaseBuilder? _redirect; + BaseBuilder get redirect => _$this._redirect ??= BaseBuilder(); + set redirect(covariant BaseBuilder? redirect) => _$this._redirect = redirect; + + int? _redirectBaseType; + int? get redirectBaseType => _$this._redirectBaseType; + set redirectBaseType(covariant int? redirectBaseType) => _$this._redirectBaseType = redirectBaseType; + + JsonObject? _redirectEmptyType; + JsonObject? get redirectEmptyType => _$this._redirectEmptyType; + set redirectEmptyType(covariant JsonObject? redirectEmptyType) => _$this._redirectEmptyType = redirectEmptyType; + + NestedRedirectBuilder(); + + NestedRedirectBuilder get _$this { + final $v = _$v; + if ($v != null) { + _redirect = $v.redirect?.toBuilder(); + _redirectBaseType = $v.redirectBaseType; + _redirectEmptyType = $v.redirectEmptyType; + _$v = null; + } + return this; + } + + @override + void replace(covariant NestedRedirect other) { + ArgumentError.checkNotNull(other, 'other'); + _$v = other as _$NestedRedirect; + } + + @override + void update(void Function(NestedRedirectBuilder)? updates) { + if (updates != null) updates(this); + } + + @override + NestedRedirect build() => _build(); + + _$NestedRedirect _build() { + _$NestedRedirect _$result; + try { + _$result = _$v ?? + _$NestedRedirect._( + redirect: _redirect?.build(), redirectBaseType: redirectBaseType, redirectEmptyType: redirectEmptyType); + } catch (_) { + late String _$failedField; + try { + _$failedField = 'redirect'; + _redirect?.build(); + } catch (e) { + throw BuiltValueNestedFieldError(r'NestedRedirect', _$failedField, e.toString()); + } + rethrow; + } + replace(_$result); + return _$result; + } +} + +abstract mixin class SomeOfRedirectInterfaceBuilder { + void replace(SomeOfRedirectInterface other); + void update(void Function(SomeOfRedirectInterfaceBuilder) updates); + BaseBuilder get base; + set base(BaseBuilder? base); + + int? get $int; + set $int(int? $int); + + JsonObject? get jsonObject; + set jsonObject(JsonObject? jsonObject); +} + +class _$SomeOfRedirect extends SomeOfRedirect { + @override + final JsonObject data; + @override + final Base? base; + @override + final int? $int; + @override + final JsonObject? jsonObject; + + factory _$SomeOfRedirect([void Function(SomeOfRedirectBuilder)? updates]) => + (SomeOfRedirectBuilder()..update(updates))._build(); + + _$SomeOfRedirect._({required this.data, this.base, this.$int, this.jsonObject}) : super._() { + BuiltValueNullFieldError.checkNotNull(data, r'SomeOfRedirect', 'data'); + } + + @override + SomeOfRedirect rebuild(void Function(SomeOfRedirectBuilder) updates) => (toBuilder()..update(updates)).build(); + + @override + SomeOfRedirectBuilder toBuilder() => SomeOfRedirectBuilder()..replace(this); + + @override + bool operator ==(Object other) { + if (identical(other, this)) return true; + return other is SomeOfRedirect && + data == other.data && + base == other.base && + $int == other.$int && + jsonObject == other.jsonObject; + } + + @override + int get hashCode { + var _$hash = 0; + _$hash = $jc(_$hash, data.hashCode); + _$hash = $jc(_$hash, base.hashCode); + _$hash = $jc(_$hash, $int.hashCode); + _$hash = $jc(_$hash, jsonObject.hashCode); + _$hash = $jf(_$hash); + return _$hash; + } + + @override + String toString() { + return (newBuiltValueToStringHelper(r'SomeOfRedirect') + ..add('data', data) + ..add('base', base) + ..add('\$int', $int) + ..add('jsonObject', jsonObject)) + .toString(); + } +} + +class SomeOfRedirectBuilder implements Builder, SomeOfRedirectInterfaceBuilder { + _$SomeOfRedirect? _$v; + + JsonObject? _data; + JsonObject? get data => _$this._data; + set data(covariant JsonObject? data) => _$this._data = data; + + BaseBuilder? _base; + BaseBuilder get base => _$this._base ??= BaseBuilder(); + set base(covariant BaseBuilder? base) => _$this._base = base; + + int? _$int; + int? get $int => _$this._$int; + set $int(covariant int? $int) => _$this._$int = $int; + + JsonObject? _jsonObject; + JsonObject? get jsonObject => _$this._jsonObject; + set jsonObject(covariant JsonObject? jsonObject) => _$this._jsonObject = jsonObject; + + SomeOfRedirectBuilder(); + + SomeOfRedirectBuilder get _$this { + final $v = _$v; + if ($v != null) { + _data = $v.data; + _base = $v.base?.toBuilder(); + _$int = $v.$int; + _jsonObject = $v.jsonObject; + _$v = null; + } + return this; + } + + @override + void replace(covariant SomeOfRedirect other) { + ArgumentError.checkNotNull(other, 'other'); + _$v = other as _$SomeOfRedirect; + } + + @override + void update(void Function(SomeOfRedirectBuilder)? updates) { + if (updates != null) updates(this); + } + + @override + SomeOfRedirect build() => _build(); + + _$SomeOfRedirect _build() { + SomeOfRedirect._validate(this); + _$SomeOfRedirect _$result; + try { + _$result = _$v ?? + _$SomeOfRedirect._( + data: BuiltValueNullFieldError.checkNotNull(data, r'SomeOfRedirect', 'data'), + base: _base?.build(), + $int: $int, + jsonObject: jsonObject); + } catch (_) { + late String _$failedField; + try { + _$failedField = 'base'; + _base?.build(); + } catch (e) { + throw BuiltValueNestedFieldError(r'SomeOfRedirect', _$failedField, e.toString()); + } + rethrow; + } + replace(_$result); + return _$result; + } +} + +// ignore_for_file: deprecated_member_use_from_same_package,type=lint diff --git a/packages/dynamite/dynamite_end_to_end_test/lib/type_defs.openapi.json b/packages/dynamite/dynamite_end_to_end_test/lib/type_defs.openapi.json new file mode 100644 index 00000000..0b10f4b5 --- /dev/null +++ b/packages/dynamite/dynamite_end_to_end_test/lib/type_defs.openapi.json @@ -0,0 +1,61 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "some ofs test", + "version": "0.0.1" + }, + "components": { + "schemas": { + "Base": { + "type": "object", + "properties": { + "attribute": { + "type": "string" + } + } + }, + "TypeResultBase": { + "type": "integer" + }, + "EmptySchema": {}, + "Redirect": { + "$ref": "#/components/schemas/Base" + }, + "RedirectBaseType": { + "$ref": "#/components/schemas/TypeResultBase" + }, + "RedirectEmptyType": { + "$ref": "#/components/schemas/EmptySchema" + }, + "NestedRedirect": { + "type": "object", + "properties": { + "redirect": { + "$ref": "#/components/schemas/Base" + }, + "redirectBaseType": { + "$ref": "#/components/schemas/TypeResultBase" + }, + "redirectEmptyType": { + "$ref": "#/components/schemas/EmptySchema" + } + } + }, + "SomeOfRedirect": { + "oneOf": [ + { + "$ref": "#/components/schemas/Base" + }, + { + "$ref": "#/components/schemas/TypeResultBase" + }, + { + "$ref": "#/components/schemas/EmptySchema" + } + ] + } + } + }, + "paths": {}, + "tags": [] +} diff --git a/packages/dynamite/dynamite_end_to_end_test/test/type_defs_test.dart b/packages/dynamite/dynamite_end_to_end_test/test/type_defs_test.dart new file mode 100644 index 00000000..4b39a32f --- /dev/null +++ b/packages/dynamite/dynamite_end_to_end_test/test/type_defs_test.dart @@ -0,0 +1,13 @@ +import 'package:built_value/json_object.dart'; +import 'package:dynamite_end_to_end_test/type_defs.openapi.dart'; +import 'package:test/test.dart'; + +void main() { + test('TypeDefs', () { + expect(1, isA()); + expect(JsonObject('value'), isA()); + expect(Base(), isA()); + expect(1, isA()); + expect(JsonObject('value'), isA()); + }); +}