Skip to content

Commit

Permalink
feat(dynamite): generate library for every spec
Browse files Browse the repository at this point in the history
Signed-off-by: Nikolas Rimikis <[email protected]>
  • Loading branch information
Leptopoda committed Dec 22, 2023
1 parent 96b1450 commit e41d509
Show file tree
Hide file tree
Showing 41 changed files with 257 additions and 304 deletions.
55 changes: 40 additions & 15 deletions packages/dynamite/dynamite/lib/src/builder/serializer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,44 @@ import 'package:code_builder/code_builder.dart';
import 'package:dynamite/src/builder/state.dart';

List<Spec> buildSerializer(final State state) => [
const Code('// coverage:ignore-start'),
const Code('@visibleForTesting'),
const Code('final Serializers serializers = (Serializers().toBuilder()'),
...state.resolvedTypes
.map((final type) => type.serializers)
.expand((final element) => element)
.toSet()
.map(Code.new),
const Code(').build();'),
const Code(''),
const Code('@visibleForTesting'),
const Code(
'final Serializers jsonSerializers = (serializers.toBuilder()..add(DynamiteDoubleSerializer())..addPlugin(StandardJsonPlugin())..addPlugin(const HeaderPlugin())..addPlugin(const ContentStringPlugin())).build();',
),
const Code('// coverage:ignore-end'),
const Code('// coverage:ignore-start\n'),
Field((final b) {
b
..annotations.add(refer('visibleForTesting'))
..modifier = FieldModifier.final$
..type = refer('Serializers')
..name = 'serializers';

final serializers =
state.resolvedTypes.map((final type) => type.serializers).expand((final element) => element).toSet();

final bodyBuilder = StringBuffer()
..writeln('(Serializers().toBuilder()')
..writeAll(serializers, '\n')
..writeln(').build()');

b.assignment = Code(bodyBuilder.toString());
}),
Field((final b) {
b
..annotations.add(refer('visibleForTesting'))
..modifier = FieldModifier.final$
..type = refer('Serializers')
..name = 'jsonSerializers';

const serializers = [
'..add(DynamiteDoubleSerializer())',
'..addPlugin(StandardJsonPlugin())',
'..addPlugin(const HeaderPlugin())',
'..addPlugin(const ContentStringPlugin())',
];

final bodyBuilder = StringBuffer()
..writeln('(serializers.toBuilder()')
..writeAll(serializers, '\n')
..writeln(').build()');

b.assignment = Code(bodyBuilder.toString());
}),
const Code('// coverage:ignore-end\n'),
];
4 changes: 4 additions & 0 deletions packages/dynamite/dynamite/lib/src/helpers/dart_helpers.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'package:source_helper/source_helper.dart';

String toDartName(
final String name, {
final bool uppercaseFirstCharacter = false,
Expand All @@ -22,6 +24,8 @@ String toDartName(
return result;
}

String toLibraryName(final String name) => toDartName(name).snake;

/// Helper methods to work with strings.
extension StringUtils on String {
/// Capitalizes this string.
Expand Down
51 changes: 40 additions & 11 deletions packages/dynamite/dynamite/lib/src/openapi_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@ import 'dart:async';
import 'dart:convert';

import 'package:build/build.dart';
import 'package:built_collection/built_collection.dart';
import 'package:checked_yaml/checked_yaml.dart';
import 'package:code_builder/code_builder.dart';
import 'package:dart_style/dart_style.dart';
import 'package:dynamite/src/builder/client.dart';
import 'package:dynamite/src/builder/generate_ofs.dart';
import 'package:dynamite/src/builder/generate_schemas.dart';
import 'package:dynamite/src/builder/imports.dart';
import 'package:dynamite/src/builder/serializer.dart';
import 'package:dynamite/src/builder/state.dart';
import 'package:dynamite/src/helpers/dart_helpers.dart';
import 'package:dynamite/src/helpers/version_checker.dart';
import 'package:dynamite/src/models/config.dart';
import 'package:dynamite/src/models/openapi.dart' as openapi;
import 'package:path/path.dart' as p;
import 'package:version/version.dart';

class OpenAPIBuilder implements Builder {
Expand Down Expand Up @@ -78,16 +78,45 @@ class OpenAPIBuilder implements Builder {

final state = State(buildConfig);

// Imports need to be generated after everything else so we know if we need the local part directive,
// but they need to be added to the beginning of the output.
final output = ListBuilder<Spec>()
..addAll(generateClients(spec, state))
..addAll(generateSchemas(spec, state))
..addAll(buildOfsExtensions(spec, state))
..addAll(buildSerializer(state))
..insertAll(0, generateImports(outputId, state));
final output = Library((final b) {
final analyzerIgnores = state.buildConfig.analyzerIgnores;
if (analyzerIgnores != null) {
b.ignoreForFile.addAll(analyzerIgnores);
}

b
..name = toLibraryName(p.basenameWithoutExtension(inputId.path))
..directives.addAll([
Directive.import('dart:convert'),
Directive.import('dart:typed_data'),
Directive.import('package:built_collection/built_collection.dart'),
Directive.import('package:built_value/built_value.dart'),
Directive.import('package:built_value/json_object.dart'),
Directive.import('package:built_value/serializer.dart'),
Directive.import('package:built_value/standard_json_plugin.dart'),
Directive.import('package:collection/collection.dart'),
Directive.import('package:dynamite_runtime/built_value.dart'),
Directive.import('package:dynamite_runtime/http_client.dart'),
Directive.import('package:dynamite_runtime/models.dart'),
Directive.import('package:dynamite_runtime/utils.dart', as: 'dynamite_utils'),
Directive.import('package:meta/meta.dart'),
Directive.import('package:universal_io/io.dart'),
Directive.import('package:uri/uri.dart'),
])
..body.addAll(generateClients(spec, state))
..body.addAll(generateSchemas(spec, state))
..body.addAll(buildOfsExtensions(spec, state))
..body.addAll(buildSerializer(state));

// Part directive need to be generated after everything else so we know if we need it.
if (state.hasResolvedBuiltTypes) {
b.directives.add(
Directive.part(p.basename(outputId.changeExtension('.g.dart').path)),
);
}
});

var outputString = output.build().map((final e) => e.accept(emitter)).join('\n');
var outputString = output.accept(emitter).toString();

final coverageIgnores = state.buildConfig.coverageIgnores;
if (coverageIgnores != null) {
Expand Down
1 change: 1 addition & 0 deletions packages/dynamite/dynamite/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ dependencies:
path: ^1.0.0
pub_semver: ^2.1.4
pubspec_parse: ^1.2.3
source_helper: ^1.3.0
uri: ^1.0.0
version: ^3.0.0

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// ignore_for_file: camel_case_types
// ignore_for_file: discarded_futures
// ignore_for_file: public_member_api_docs
// ignore_for_file: unreachable_switch_case
// ignore_for_file: unused_element
// ignore_for_file: camel_case_types, discarded_futures
// ignore_for_file: no_leading_underscores_for_local_identifiers
// ignore_for_file: public_member_api_docs, unreachable_switch_case
// ignore_for_file: unused_element

library all_of_openapi;

import 'package:built_value/built_value.dart';
import 'package:built_value/serializer.dart';
Expand Down Expand Up @@ -137,7 +137,6 @@ final Serializers serializers = (Serializers().toBuilder()
..addBuilderFactory(const FullType(OneValueAllOf), OneValueAllOfBuilder.new)
..add(OneValueAllOf.serializer))
.build();

@visibleForTesting
final Serializers jsonSerializers = (serializers.toBuilder()
..add(DynamiteDoubleSerializer())
Expand Down
17 changes: 5 additions & 12 deletions packages/dynamite/dynamite_end_to_end_test/lib/any_of.openapi.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// ignore_for_file: camel_case_types
// ignore_for_file: discarded_futures
// ignore_for_file: public_member_api_docs
// ignore_for_file: unreachable_switch_case
// ignore_for_file: unused_element
// ignore_for_file: camel_case_types, discarded_futures
// ignore_for_file: no_leading_underscores_for_local_identifiers
// ignore_for_file: public_member_api_docs, unreachable_switch_case
// ignore_for_file: unused_element

library any_of_openapi;

import 'package:built_value/built_value.dart';
import 'package:built_value/serializer.dart';
Expand All @@ -15,11 +15,8 @@ import 'package:meta/meta.dart';
part 'any_of.openapi.g.dart';

typedef OneObjectAnyOf = OneObjectAnyOf0;

typedef OneValueAnyOf = String;

typedef AnyOfIntDouble = num;

typedef AnyOfIntDoubleNum = num;

@BuiltValue(instantiable: false)
Expand Down Expand Up @@ -95,11 +92,8 @@ abstract class OneObjectAnyOf0 implements $OneObjectAnyOf0Interface, Built<OneOb
}

typedef ObjectAnyOf = ({ObjectAnyOf0? objectAnyOf0, ObjectAnyOf1? objectAnyOf1});

typedef MixedAnyOf = ({MixedAnyOf1? mixedAnyOf1, String? string});

typedef AnyOfIntDoubleOther = ({num? $num, String? string});

typedef $ObjectAnyOf0ObjectAnyOf1 = ({ObjectAnyOf0? objectAnyOf0, ObjectAnyOf1? objectAnyOf1});

extension $ObjectAnyOf0ObjectAnyOf1Extension on $ObjectAnyOf0ObjectAnyOf1 {
Expand Down Expand Up @@ -286,7 +280,6 @@ final Serializers serializers = (Serializers().toBuilder()
..add(OneObjectAnyOf0.serializer)
..add($NumStringExtension.serializer))
.build();

@visibleForTesting
final Serializers jsonSerializers = (serializers.toBuilder()
..add(DynamiteDoubleSerializer())
Expand Down
11 changes: 5 additions & 6 deletions packages/dynamite/dynamite_end_to_end_test/lib/enum.openapi.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// ignore_for_file: camel_case_types
// ignore_for_file: discarded_futures
// ignore_for_file: public_member_api_docs
// ignore_for_file: unreachable_switch_case
// ignore_for_file: unused_element
// ignore_for_file: camel_case_types, discarded_futures
// ignore_for_file: no_leading_underscores_for_local_identifiers
// ignore_for_file: public_member_api_docs, unreachable_switch_case
// ignore_for_file: unused_element

library enum_openapi;

import 'package:built_collection/built_collection.dart';
import 'package:built_value/built_value.dart';
Expand Down Expand Up @@ -336,7 +336,6 @@ final Serializers serializers = (Serializers().toBuilder()
..add(WrappedEnum_CustomString.serializer)
..add(WrappedEnum_Integer.serializer))
.build();

@visibleForTesting
final Serializers jsonSerializers = (serializers.toBuilder()
..add(DynamiteDoubleSerializer())
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
// ignore_for_file: camel_case_types
// ignore_for_file: discarded_futures
// ignore_for_file: public_member_api_docs
// ignore_for_file: unreachable_switch_case
// ignore_for_file: unused_element
// ignore_for_file: camel_case_types, discarded_futures
// ignore_for_file: no_leading_underscores_for_local_identifiers
// ignore_for_file: public_member_api_docs, unreachable_switch_case
// ignore_for_file: unused_element

library headers_openapi;

import 'dart:typed_data';

import 'package:built_value/built_value.dart';
Expand Down Expand Up @@ -237,7 +238,6 @@ final Serializers serializers = (Serializers().toBuilder()
..addBuilderFactory(const FullType(GetWithContentHeaders), GetWithContentHeadersBuilder.new)
..add(GetWithContentHeaders.serializer))
.build();

@visibleForTesting
final Serializers jsonSerializers = (serializers.toBuilder()
..add(DynamiteDoubleSerializer())
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// ignore_for_file: camel_case_types
// ignore_for_file: discarded_futures
// ignore_for_file: public_member_api_docs
// ignore_for_file: unreachable_switch_case
// ignore_for_file: unused_element
// ignore_for_file: camel_case_types, discarded_futures
// ignore_for_file: no_leading_underscores_for_local_identifiers
// ignore_for_file: public_member_api_docs, unreachable_switch_case
// ignore_for_file: unused_element

library interfaces_openapi;

import 'package:built_value/built_value.dart';
import 'package:built_value/serializer.dart';
Expand Down Expand Up @@ -55,7 +55,6 @@ final Serializers serializers = (Serializers().toBuilder()
..addBuilderFactory(const FullType(BaseInterface), BaseInterfaceBuilder.new)
..add(BaseInterface.serializer))
.build();

@visibleForTesting
final Serializers jsonSerializers = (serializers.toBuilder()
..add(DynamiteDoubleSerializer())
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// ignore_for_file: camel_case_types
// ignore_for_file: discarded_futures
// ignore_for_file: public_member_api_docs
// ignore_for_file: unreachable_switch_case
// ignore_for_file: unused_element
// ignore_for_file: camel_case_types, discarded_futures
// ignore_for_file: no_leading_underscores_for_local_identifiers
// ignore_for_file: public_member_api_docs, unreachable_switch_case
// ignore_for_file: unused_element

library nested_ofs_openapi;

import 'package:built_value/built_value.dart';
import 'package:built_value/serializer.dart';
Expand Down Expand Up @@ -139,27 +139,22 @@ abstract class BaseNestedAnyOf3
}

typedef BaseOneOf = ({BaseOneOf1? baseOneOf1, double? $double});

typedef BaseAnyOf = ({BaseAnyOf1? baseAnyOf1, int? $int});

typedef BaseNestedOneOf = ({
BaseAllOf? baseAllOf,
BaseAnyOf? baseAnyOf,
BaseNestedOneOf3? baseNestedOneOf3,
BaseOneOf1? baseOneOf1,
double? $double
});

typedef BaseNestedAnyOf = ({
BaseAllOf? baseAllOf,
BaseAnyOf1? baseAnyOf1,
BaseNestedAnyOf3? baseNestedAnyOf3,
BaseOneOf? baseOneOf,
int? $int
});

typedef NestedOptimizedOneOf = ({BaseOneOf1? baseOneOf1, num? $num});

typedef $BaseOneOf1Double = ({BaseOneOf1? baseOneOf1, double? $double});

extension $BaseOneOf1DoubleExtension on $BaseOneOf1Double {
Expand Down Expand Up @@ -550,7 +545,6 @@ final Serializers serializers = (Serializers().toBuilder()
..add($BaseAllOfBaseAnyOf1BaseNestedAnyOf3BaseOneOfIntExtension.serializer)
..add($BaseOneOf1NumExtension.serializer))
.build();

@visibleForTesting
final Serializers jsonSerializers = (serializers.toBuilder()
..add(DynamiteDoubleSerializer())
Expand Down
17 changes: 5 additions & 12 deletions packages/dynamite/dynamite_end_to_end_test/lib/one_of.openapi.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// ignore_for_file: camel_case_types
// ignore_for_file: discarded_futures
// ignore_for_file: public_member_api_docs
// ignore_for_file: unreachable_switch_case
// ignore_for_file: unused_element
// ignore_for_file: camel_case_types, discarded_futures
// ignore_for_file: no_leading_underscores_for_local_identifiers
// ignore_for_file: public_member_api_docs, unreachable_switch_case
// ignore_for_file: unused_element

library one_of_openapi;

import 'package:built_value/built_value.dart';
import 'package:built_value/serializer.dart';
Expand All @@ -15,11 +15,8 @@ import 'package:meta/meta.dart';
part 'one_of.openapi.g.dart';

typedef OneObjectOneOf = OneObjectOneOf0;

typedef OneValueOneOf = String;

typedef OneOfIntDouble = num;

typedef OneOfIntDoubleNum = num;

@BuiltValue(instantiable: false)
Expand Down Expand Up @@ -95,11 +92,8 @@ abstract class OneObjectOneOf0 implements $OneObjectOneOf0Interface, Built<OneOb
}

typedef ObjectOneOf = ({ObjectOneOf0? objectOneOf0, ObjectOneOf1? objectOneOf1});

typedef MixedOneOf = ({MixedOneOf1? mixedOneOf1, String? string});

typedef OneOfIntDoubleOther = ({num? $num, String? string});

typedef $ObjectOneOf0ObjectOneOf1 = ({ObjectOneOf0? objectOneOf0, ObjectOneOf1? objectOneOf1});

extension $ObjectOneOf0ObjectOneOf1Extension on $ObjectOneOf0ObjectOneOf1 {
Expand Down Expand Up @@ -286,7 +280,6 @@ final Serializers serializers = (Serializers().toBuilder()
..add(OneObjectOneOf0.serializer)
..add($NumStringExtension.serializer))
.build();

@visibleForTesting
final Serializers jsonSerializers = (serializers.toBuilder()
..add(DynamiteDoubleSerializer())
Expand Down
Loading

0 comments on commit e41d509

Please sign in to comment.