From c54d4f86561cb856734f97ccfea5611d074f40d4 Mon Sep 17 00:00:00 2001 From: Nikolas Rimikis Date: Sat, 4 Nov 2023 14:13:31 +0100 Subject: [PATCH 1/3] feat(dynamite): allow per spec configuration Signed-off-by: Nikolas Rimikis --- packages/dynamite/dynamite/README.md | 5 ++ .../src/models/dynamite_config/config.dart | 50 +++++++++++++++++++ .../src/models/dynamite_config/config.g.dart | 37 ++++++++++++-- .../dynamite/lib/src/openapi_builder.dart | 17 ++++--- 4 files changed, 96 insertions(+), 13 deletions(-) diff --git a/packages/dynamite/dynamite/README.md b/packages/dynamite/dynamite/README.md index 020c3afb7df..66bf01236c6 100644 --- a/packages/dynamite/dynamite/README.md +++ b/packages/dynamite/dynamite/README.md @@ -53,6 +53,11 @@ targets: - 'factory .*\.fromJson\(Map json\) => jsonSerializers\.deserializeWith\(serializer, json\)!;' - 'Map toJson\(\) => jsonSerializers\.serializeWith\(serializer, this\)! as Map;' - 'static BuiltSet<.*> get values => _\$.*Values;' + overrides: + # Tighten linting rules for specific specs + lib/my_spec.openapi.json: + analyzer_ignores: + - camel_case_types ``` diff --git a/packages/dynamite/dynamite/lib/src/models/dynamite_config/config.dart b/packages/dynamite/dynamite/lib/src/models/dynamite_config/config.dart index 6c6439087e4..57b46ebc854 100644 --- a/packages/dynamite/dynamite/lib/src/models/dynamite_config/config.dart +++ b/packages/dynamite/dynamite/lib/src/models/dynamite_config/config.dart @@ -33,6 +33,56 @@ abstract class DynamiteConfig implements Built? get overrides; + + /// Gets the config for the given [uri]. + /// + /// Returns this if no override is set. + DynamiteConfig configFor(final String uri) { + if (overrides == null) { + return this; + } + + DynamiteConfig? override; + for (final entry in overrides!.entries) { + if (entry.key == uri) { + override = entry.value; + break; + } + } + + if (override == null) { + return this; + } + + return merge(override); + } + + /// Merges `this` config with the given [override]. + /// + /// Throws a [ArgumentError] if the override has overrides itself. + DynamiteConfig merge(final DynamiteConfig other) { + if (other.overrides != null) { + throw ArgumentError('Configs can only be merged with a config that does not have further overrides'); + } + + return rebuild((final b) { + final analyzerIgnores = other.analyzerIgnores; + if (analyzerIgnores != null) { + b.analyzerIgnores.replace(analyzerIgnores); + } + + final coverageIgnores = other.coverageIgnores; + if (coverageIgnores != null) { + b.coverageIgnores.replace(coverageIgnores); + } + }); + } } @SerializersFor([ diff --git a/packages/dynamite/dynamite/lib/src/models/dynamite_config/config.g.dart b/packages/dynamite/dynamite/lib/src/models/dynamite_config/config.g.dart index 0903b8d2fc2..21a1c259ea0 100644 --- a/packages/dynamite/dynamite/lib/src/models/dynamite_config/config.g.dart +++ b/packages/dynamite/dynamite/lib/src/models/dynamite_config/config.g.dart @@ -9,7 +9,9 @@ part of 'config.dart'; Serializers _$_serializers = (Serializers().toBuilder() ..add(DynamiteConfig.serializer) ..addBuilderFactory(const FullType(BuiltSet, [FullType(String)]), () => SetBuilder()) - ..addBuilderFactory(const FullType(BuiltSet, [FullType(String)]), () => SetBuilder())) + ..addBuilderFactory(const FullType(BuiltSet, [FullType(String)]), () => SetBuilder()) + ..addBuilderFactory(const FullType(BuiltMap, [FullType(String), FullType(DynamiteConfig)]), + () => MapBuilder())) .build(); Serializer _$dynamiteConfigSerializer = _$DynamiteConfigSerializer(); @@ -42,6 +44,13 @@ class _$DynamiteConfigSerializer implements StructuredSerializer ..add('pageWidth') ..add(serializers.serialize(value, specifiedType: const FullType(int))); } + value = object.overrides; + if (value != null) { + result + ..add('overrides') + ..add(serializers.serialize(value, + specifiedType: const FullType(BuiltMap, [FullType(String), FullType(DynamiteConfig)]))); + } return result; } @@ -67,6 +76,10 @@ class _$DynamiteConfigSerializer implements StructuredSerializer case 'pageWidth': result.pageWidth = serializers.deserialize(value, specifiedType: const FullType(int)) as int?; break; + case 'overrides': + result.overrides.replace(serializers.deserialize(value, + specifiedType: const FullType(BuiltMap, [FullType(String), FullType(DynamiteConfig)]))!); + break; } } @@ -81,11 +94,13 @@ class _$DynamiteConfig extends DynamiteConfig { final BuiltSet? coverageIgnores; @override final int? pageWidth; + @override + final BuiltMap? overrides; factory _$DynamiteConfig([void Function(DynamiteConfigBuilder)? updates]) => (DynamiteConfigBuilder()..update(updates))._build(); - _$DynamiteConfig._({this.analyzerIgnores, this.coverageIgnores, this.pageWidth}) : super._(); + _$DynamiteConfig._({this.analyzerIgnores, this.coverageIgnores, this.pageWidth, this.overrides}) : super._(); @override DynamiteConfig rebuild(void Function(DynamiteConfigBuilder) updates) => (toBuilder()..update(updates)).build(); @@ -99,7 +114,8 @@ class _$DynamiteConfig extends DynamiteConfig { return other is DynamiteConfig && analyzerIgnores == other.analyzerIgnores && coverageIgnores == other.coverageIgnores && - pageWidth == other.pageWidth; + pageWidth == other.pageWidth && + overrides == other.overrides; } @override @@ -108,6 +124,7 @@ class _$DynamiteConfig extends DynamiteConfig { _$hash = $jc(_$hash, analyzerIgnores.hashCode); _$hash = $jc(_$hash, coverageIgnores.hashCode); _$hash = $jc(_$hash, pageWidth.hashCode); + _$hash = $jc(_$hash, overrides.hashCode); _$hash = $jf(_$hash); return _$hash; } @@ -117,7 +134,8 @@ class _$DynamiteConfig extends DynamiteConfig { return (newBuiltValueToStringHelper(r'DynamiteConfig') ..add('analyzerIgnores', analyzerIgnores) ..add('coverageIgnores', coverageIgnores) - ..add('pageWidth', pageWidth)) + ..add('pageWidth', pageWidth) + ..add('overrides', overrides)) .toString(); } } @@ -137,6 +155,10 @@ class DynamiteConfigBuilder implements Builder _$this._pageWidth; set pageWidth(int? pageWidth) => _$this._pageWidth = pageWidth; + MapBuilder? _overrides; + MapBuilder get overrides => _$this._overrides ??= MapBuilder(); + set overrides(MapBuilder? overrides) => _$this._overrides = overrides; + DynamiteConfigBuilder(); DynamiteConfigBuilder get _$this { @@ -145,6 +167,7 @@ class DynamiteConfigBuilder implements Builder openapi.serializers.deserializeWith( openapi.OpenAPI.serializer, @@ -76,7 +76,8 @@ class OpenAPIBuilder implements Builder { throw Exception('Only OpenAPI between $minSupportedVersion and $maxSupportedVersion are supported.'); } - final state = State(buildConfig); + final config = buildConfig.configFor(inputId.path); + final state = State(config); final output = Library((final b) { final analyzerIgnores = state.buildConfig.analyzerIgnores; From 34ae94c4625d24b97cae06e2a40796f2539e2f08 Mon Sep 17 00:00:00 2001 From: Nikolas Rimikis Date: Thu, 21 Dec 2023 17:49:45 +0100 Subject: [PATCH 2/3] feat(dynamite): add ability to mark clients as experimental Signed-off-by: Nikolas Rimikis --- packages/dynamite/dynamite/README.md | 2 ++ .../src/models/dynamite_config/config.dart | 10 ++++++ .../src/models/dynamite_config/config.g.dart | 35 +++++++++++++++---- .../dynamite/lib/src/openapi_builder.dart | 6 ++++ 4 files changed, 47 insertions(+), 6 deletions(-) diff --git a/packages/dynamite/dynamite/README.md b/packages/dynamite/dynamite/README.md index 66bf01236c6..2d481c23e23 100644 --- a/packages/dynamite/dynamite/README.md +++ b/packages/dynamite/dynamite/README.md @@ -55,9 +55,11 @@ targets: - 'static BuiltSet<.*> get values => _\$.*Values;' overrides: # Tighten linting rules for specific specs + # Mark the generated library as experimental lib/my_spec.openapi.json: analyzer_ignores: - camel_case_types + experimental: true ``` diff --git a/packages/dynamite/dynamite/lib/src/models/dynamite_config/config.dart b/packages/dynamite/dynamite/lib/src/models/dynamite_config/config.dart index 57b46ebc854..3a47acfe4ca 100644 --- a/packages/dynamite/dynamite/lib/src/models/dynamite_config/config.dart +++ b/packages/dynamite/dynamite/lib/src/models/dynamite_config/config.dart @@ -40,6 +40,14 @@ abstract class DynamiteConfig implements Built? get overrides; + /// Whether the generated library should be marked with the `@experimental` annotation. + bool get experimental; + + @BuiltValueHook(initializeBuilder: true) + static void _defaults(final DynamiteConfigBuilder b) { + b.experimental ??= false; + } + /// Gets the config for the given [uri]. /// /// Returns this if no override is set. @@ -81,6 +89,8 @@ abstract class DynamiteConfig implements Built @override Iterable serialize(Serializers serializers, DynamiteConfig object, {FullType specifiedType = FullType.unspecified}) { - final result = []; + final result = [ + 'experimental', + serializers.serialize(object.experimental, specifiedType: const FullType(bool)), + ]; Object? value; value = object.analyzerIgnores; if (value != null) { @@ -80,6 +83,9 @@ class _$DynamiteConfigSerializer implements StructuredSerializer result.overrides.replace(serializers.deserialize(value, specifiedType: const FullType(BuiltMap, [FullType(String), FullType(DynamiteConfig)]))!); break; + case 'experimental': + result.experimental = serializers.deserialize(value, specifiedType: const FullType(bool))! as bool; + break; } } @@ -96,11 +102,17 @@ class _$DynamiteConfig extends DynamiteConfig { final int? pageWidth; @override final BuiltMap? overrides; + @override + final bool experimental; factory _$DynamiteConfig([void Function(DynamiteConfigBuilder)? updates]) => (DynamiteConfigBuilder()..update(updates))._build(); - _$DynamiteConfig._({this.analyzerIgnores, this.coverageIgnores, this.pageWidth, this.overrides}) : super._(); + _$DynamiteConfig._( + {this.analyzerIgnores, this.coverageIgnores, this.pageWidth, this.overrides, required this.experimental}) + : super._() { + BuiltValueNullFieldError.checkNotNull(experimental, r'DynamiteConfig', 'experimental'); + } @override DynamiteConfig rebuild(void Function(DynamiteConfigBuilder) updates) => (toBuilder()..update(updates)).build(); @@ -115,7 +127,8 @@ class _$DynamiteConfig extends DynamiteConfig { analyzerIgnores == other.analyzerIgnores && coverageIgnores == other.coverageIgnores && pageWidth == other.pageWidth && - overrides == other.overrides; + overrides == other.overrides && + experimental == other.experimental; } @override @@ -125,6 +138,7 @@ class _$DynamiteConfig extends DynamiteConfig { _$hash = $jc(_$hash, coverageIgnores.hashCode); _$hash = $jc(_$hash, pageWidth.hashCode); _$hash = $jc(_$hash, overrides.hashCode); + _$hash = $jc(_$hash, experimental.hashCode); _$hash = $jf(_$hash); return _$hash; } @@ -135,7 +149,8 @@ class _$DynamiteConfig extends DynamiteConfig { ..add('analyzerIgnores', analyzerIgnores) ..add('coverageIgnores', coverageIgnores) ..add('pageWidth', pageWidth) - ..add('overrides', overrides)) + ..add('overrides', overrides) + ..add('experimental', experimental)) .toString(); } } @@ -159,7 +174,13 @@ class DynamiteConfigBuilder implements Builder get overrides => _$this._overrides ??= MapBuilder(); set overrides(MapBuilder? overrides) => _$this._overrides = overrides; - DynamiteConfigBuilder(); + bool? _experimental; + bool? get experimental => _$this._experimental; + set experimental(bool? experimental) => _$this._experimental = experimental; + + DynamiteConfigBuilder() { + DynamiteConfig._defaults(this); + } DynamiteConfigBuilder get _$this { final $v = _$v; @@ -168,6 +189,7 @@ class DynamiteConfigBuilder implements Builder Date: Fri, 22 Dec 2023 09:16:08 +0100 Subject: [PATCH 3/3] fix(nextcloud): mark libraries with manually generated specs as experimental Signed-off-by: Nikolas Rimikis --- packages/nextcloud/build.yaml | 7 +++++++ packages/nextcloud/lib/src/api/news.openapi.dart | 1 + packages/nextcloud/lib/src/api/notes.openapi.dart | 1 + packages/nextcloud/lib/src/api/uppush.openapi.dart | 1 + 4 files changed, 10 insertions(+) diff --git a/packages/nextcloud/build.yaml b/packages/nextcloud/build.yaml index 3b4aa1efd69..0c0851e2fe8 100644 --- a/packages/nextcloud/build.yaml +++ b/packages/nextcloud/build.yaml @@ -18,3 +18,10 @@ targets: - 'factory .*\.fromJson\(Map json\) => jsonSerializers\.deserializeWith\(serializer, json\)!;' - 'Map toJson\(\) => jsonSerializers\.serializeWith\(serializer, this\)! as Map;' - 'static BuiltSet<.*> get values => _\$.*Values;' + overrides: + lib/src/api/news.openapi.json: + experimental: true + lib/src/api/notes.openapi.json: + experimental: true + lib/src/api/uppush.openapi.json: + experimental: true diff --git a/packages/nextcloud/lib/src/api/news.openapi.dart b/packages/nextcloud/lib/src/api/news.openapi.dart index f9f5cdad44f..d39869fdff2 100644 --- a/packages/nextcloud/lib/src/api/news.openapi.dart +++ b/packages/nextcloud/lib/src/api/news.openapi.dart @@ -2,6 +2,7 @@ // ignore_for_file: no_leading_underscores_for_local_identifiers // ignore_for_file: public_member_api_docs, unreachable_switch_case +@experimental library news_openapi; import 'package:built_collection/built_collection.dart'; diff --git a/packages/nextcloud/lib/src/api/notes.openapi.dart b/packages/nextcloud/lib/src/api/notes.openapi.dart index 8f59b28093b..dd4de3ca4db 100644 --- a/packages/nextcloud/lib/src/api/notes.openapi.dart +++ b/packages/nextcloud/lib/src/api/notes.openapi.dart @@ -2,6 +2,7 @@ // ignore_for_file: no_leading_underscores_for_local_identifiers // ignore_for_file: public_member_api_docs, unreachable_switch_case +@experimental library notes_openapi; import 'dart:convert'; diff --git a/packages/nextcloud/lib/src/api/uppush.openapi.dart b/packages/nextcloud/lib/src/api/uppush.openapi.dart index adff598d0d1..373fd46be28 100644 --- a/packages/nextcloud/lib/src/api/uppush.openapi.dart +++ b/packages/nextcloud/lib/src/api/uppush.openapi.dart @@ -2,6 +2,7 @@ // ignore_for_file: no_leading_underscores_for_local_identifiers // ignore_for_file: public_member_api_docs, unreachable_switch_case +@experimental library uppush_openapi; import 'package:built_collection/built_collection.dart';