diff --git a/packages/shorebird_cli/lib/src/metadata/create_patch_metadata.g.dart b/packages/shorebird_cli/lib/src/metadata/create_patch_metadata.g.dart index eb8f636c..78e1cdd6 100644 --- a/packages/shorebird_cli/lib/src/metadata/create_patch_metadata.g.dart +++ b/packages/shorebird_cli/lib/src/metadata/create_patch_metadata.g.dart @@ -17,7 +17,7 @@ CreatePatchMetadata _$CreatePatchMetadataFromJson( final val = CreatePatchMetadata( releasePlatform: $checkedConvert( 'release_platform', - (v) => $enumDecode(_$ReleasePlatformEnumMap, v), + (v) => ReleasePlatform.fromJson(v as String), ), usedIgnoreAssetChangesFlag: $checkedConvert( 'used_ignore_asset_changes_flag', @@ -70,7 +70,7 @@ CreatePatchMetadata _$CreatePatchMetadataFromJson( Map _$CreatePatchMetadataToJson( CreatePatchMetadata instance, ) => { - 'release_platform': _$ReleasePlatformEnumMap[instance.releasePlatform]!, + 'release_platform': instance.releasePlatform.toJson(), 'used_ignore_asset_changes_flag': instance.usedIgnoreAssetChangesFlag, 'has_asset_changes': instance.hasAssetChanges, 'used_ignore_native_changes_flag': instance.usedIgnoreNativeChangesFlag, @@ -82,11 +82,3 @@ Map _$CreatePatchMetadataToJson( 'environment': instance.environment.toJson(), 'build_trace_summary': instance.buildTraceSummary, }; - -const _$ReleasePlatformEnumMap = { - ReleasePlatform.android: 'android', - ReleasePlatform.ios: 'ios', - ReleasePlatform.linux: 'linux', - ReleasePlatform.macos: 'macos', - ReleasePlatform.windows: 'windows', -}; diff --git a/packages/shorebird_cli/lib/src/metadata/update_release_metadata.g.dart b/packages/shorebird_cli/lib/src/metadata/update_release_metadata.g.dart index 56101d73..2487e370 100644 --- a/packages/shorebird_cli/lib/src/metadata/update_release_metadata.g.dart +++ b/packages/shorebird_cli/lib/src/metadata/update_release_metadata.g.dart @@ -17,7 +17,7 @@ UpdateReleaseMetadata _$UpdateReleaseMetadataFromJson( final val = UpdateReleaseMetadata( releasePlatform: $checkedConvert( 'release_platform', - (v) => $enumDecode(_$ReleasePlatformEnumMap, v), + (v) => ReleasePlatform.fromJson(v as String), ), flutterVersionOverride: $checkedConvert( 'flutter_version_override', @@ -51,18 +51,10 @@ UpdateReleaseMetadata _$UpdateReleaseMetadataFromJson( Map _$UpdateReleaseMetadataToJson( UpdateReleaseMetadata instance, ) => { - 'release_platform': _$ReleasePlatformEnumMap[instance.releasePlatform]!, + 'release_platform': instance.releasePlatform.toJson(), 'flutter_version_override': instance.flutterVersionOverride, 'generated_apks': instance.generatedApks, 'includes_public_key': instance.includesPublicKey, 'environment': instance.environment.toJson(), 'build_trace_summary': instance.buildTraceSummary, }; - -const _$ReleasePlatformEnumMap = { - ReleasePlatform.android: 'android', - ReleasePlatform.ios: 'ios', - ReleasePlatform.linux: 'linux', - ReleasePlatform.macos: 'macos', - ReleasePlatform.windows: 'windows', -}; diff --git a/packages/shorebird_cli/test/src/code_push_client_wrapper_test.dart b/packages/shorebird_cli/test/src/code_push_client_wrapper_test.dart index 52169f2f..3e707649 100644 --- a/packages/shorebird_cli/test/src/code_push_client_wrapper_test.dart +++ b/packages/shorebird_cli/test/src/code_push_client_wrapper_test.dart @@ -297,11 +297,11 @@ void main() { test('returns organization memberships on success', () async { final expectedMemberships = [ OrganizationMembership( - organization: Organization.forTest(), + organization: organizationForTest(), role: Role.admin, ), OrganizationMembership( - organization: Organization.forTest(), + organization: organizationForTest(), role: Role.developer, ), ]; diff --git a/packages/shorebird_cli/test/src/commands/init_command_test.dart b/packages/shorebird_cli/test/src/commands/init_command_test.dart index 2c733792..608c3edc 100644 --- a/packages/shorebird_cli/test/src/commands/init_command_test.dart +++ b/packages/shorebird_cli/test/src/commands/init_command_test.dart @@ -99,7 +99,7 @@ environment: (_) async => [ OrganizationMembership( role: Role.owner, - organization: Organization.forTest(id: organizationId), + organization: organizationForTest(id: organizationId), ), ], ); @@ -442,7 +442,7 @@ Please make sure you are running "shorebird init" from within your Flutter proje (_) async => [ OrganizationMembership( role: Role.owner, - organization: Organization.forTest(id: organizationId), + organization: organizationForTest(id: organizationId), ), ], ); @@ -470,8 +470,8 @@ Please make sure you are running "shorebird init" from within your Flutter proje }); group('when user has multiple organizations', () { - final org1 = Organization.forTest(name: 'org1', id: 1); - final org2 = Organization.forTest( + final org1 = organizationForTest(name: 'org1', id: 1); + final org2 = organizationForTest( name: 'org2', id: 2, organizationType: OrganizationType.team, diff --git a/packages/shorebird_code_push_client/lib/src/code_push_client.dart b/packages/shorebird_code_push_client/lib/src/code_push_client.dart index c177c5e7..58484feb 100644 --- a/packages/shorebird_code_push_client/lib/src/code_push_client.dart +++ b/packages/shorebird_code_push_client/lib/src/code_push_client.dart @@ -190,15 +190,22 @@ class CodePushClient { ); final file = await http.MultipartFile.fromPath('file', artifactPath); - final payload = CreateReleaseArtifactRequest( - arch: arch, - platform: platform, - hash: hash, - size: file.length, - canSideload: canSideload, - filename: p.basename(artifactPath), - podfileLockHash: podfileLockHash, - ).toJson().map((key, value) => MapEntry(key, '$value')); + // `toJson` returns proper JSON types; multipart fields are always + // strings on the wire. Drop null-valued keys so absent-optional + // fields don't send the literal string "null" (previously handled + // by `@JsonKey(includeIfNull: false)` in the handwritten model). + final payload = { + for (final entry in CreateReleaseArtifactRequest( + arch: arch, + platform: platform, + hash: hash, + size: file.length, + canSideload: canSideload, + filename: p.basename(artifactPath), + podfileLockHash: podfileLockHash, + ).toJson().entries) + if (entry.value != null) entry.key: '${entry.value}', + }; request.fields.addAll(payload); final response = await _httpClient.send(request); diff --git a/packages/shorebird_code_push_client/test/src/code_push_client_test.dart b/packages/shorebird_code_push_client/test/src/code_push_client_test.dart index 2e48f709..fec38a67 100644 --- a/packages/shorebird_code_push_client/test/src/code_push_client_test.dart +++ b/packages/shorebird_code_push_client/test/src/code_push_client_test.dart @@ -1,7 +1,6 @@ import 'dart:convert'; import 'dart:io'; -import 'package:collection/collection.dart'; import 'package:http/http.dart' as http; import 'package:mocktail/mocktail.dart'; import 'package:path/path.dart' as path; @@ -468,21 +467,18 @@ void main() { const size = 5; const canSideload = true; - group('when podfileLockHash is provided', () { + // Multipart form fields are always strings on the wire, so the + // expected payloads are spelled out as Map. + // CreateReleaseArtifactRequest.toJson() returns JSON types (bool, + // int, enum→string, etc.); the client stringifies at the multipart + // boundary and drops null-valued keys (see createReleaseArtifact + // in code_push_client.dart). + group('when podfileLockHash is null', () { test('makes the correct request', () async { final tempDir = Directory.systemTemp.createTempSync(); final fixture = File(path.join(tempDir.path, 'release.txt')) ..createSync() ..writeAsStringSync('hello'); - const expectedRequest = CreateReleaseArtifactRequest( - arch: arch, - platform: platform, - hash: hash, - size: size, - canSideload: canSideload, - filename: 'release.txt', - podfileLockHash: null, - ); try { await codePushClient.createReleaseArtifact( @@ -508,31 +504,24 @@ void main() { equals(v1('apps/$appId/releases/$releaseId/artifacts')), ); expect(request.hasHeaders(expectedHeaders), isTrue); - expect( - const MapEquality().equals( - request.fields, - expectedRequest.toJson(), - ), - isTrue, - ); + expect(request.fields, { + 'arch': arch, + 'platform': platform.name, + 'hash': hash, + 'filename': 'release.txt', + 'can_sideload': 'true', + 'size': '$size', + // podfile_lock_hash absent. + }); }); }); - group('when podfileLockHash is null', () { + group('when podfileLockHash is provided', () { test('makes the correct request', () async { final tempDir = Directory.systemTemp.createTempSync(); final fixture = File(path.join(tempDir.path, 'release.txt')) ..createSync() ..writeAsStringSync('hello'); - const expectedRequest = CreateReleaseArtifactRequest( - arch: arch, - platform: platform, - hash: hash, - size: size, - canSideload: canSideload, - filename: 'release.txt', - podfileLockHash: podfileLockHash, - ); try { await codePushClient.createReleaseArtifact( @@ -558,13 +547,15 @@ void main() { equals(v1('apps/$appId/releases/$releaseId/artifacts')), ); expect(request.hasHeaders(expectedHeaders), isTrue); - expect( - const MapEquality().equals( - request.fields, - expectedRequest.toJson(), - ), - isTrue, - ); + expect(request.fields, { + 'arch': arch, + 'platform': platform.name, + 'hash': hash, + 'filename': 'release.txt', + 'can_sideload': 'true', + 'size': '$size', + 'podfile_lock_hash': podfileLockHash, + }); }); }); @@ -2047,7 +2038,7 @@ void main() { setUp(() { membership = OrganizationMembership( role: Role.admin, - organization: Organization.forTest(), + organization: organizationForTest(), ); response = GetOrganizationsResponse(organizations: [membership]); when(() => httpClient.send(any())).thenAnswer( diff --git a/packages/shorebird_code_push_protocol/README.md b/packages/shorebird_code_push_protocol/README.md index 95d9decb..05490bfc 100644 --- a/packages/shorebird_code_push_protocol/README.md +++ b/packages/shorebird_code_push_protocol/README.md @@ -1,3 +1,22 @@ ## Shorebird CodePush Protocol The Shorebird CodePush Protocol is a Dart library which contains common interfaces used by Shorebird CodePush. + +### Regenerating from the OpenAPI spec + +Everything under `lib/src/` is generated from the public Shorebird +CodePush OpenAPI spec at [api.shorebird.dev/openapi.json](https://api.shorebird.dev/openapi.json) +(also served as [openapi.yaml](https://api.shorebird.dev/openapi.yaml) +for easier human review) by +[space_gen](https://github.com/eseidel/space_gen). To regenerate +against the latest published spec: + +```sh +dart run packages/shorebird_code_push_protocol/tool/gen.dart \ + -i https://api.shorebird.dev/openapi.json \ + -o packages/shorebird_code_push_protocol +``` + +Hand-written files (`lib/extensions/`, `lib/shorebird_code_push_protocol.dart`) +are left untouched by the generator. The version of space_gen in use is +pinned in `pubspec.yaml`. diff --git a/packages/shorebird_code_push_protocol/build.yaml b/packages/shorebird_code_push_protocol/build.yaml deleted file mode 100644 index 6f2fc8a2..00000000 --- a/packages/shorebird_code_push_protocol/build.yaml +++ /dev/null @@ -1,15 +0,0 @@ -targets: - $default: - builders: - source_gen|combining_builder: - options: - ignore_for_file: - - implicit_dynamic_parameter - - require_trailing_commas - - cast_nullable_to_non_nullable - - lines_longer_than_80_chars - json_serializable: - options: - field_rename: snake - checked: true - explicit_to_json: true diff --git a/packages/shorebird_code_push_protocol/lib/src/models/auth_provider.dart b/packages/shorebird_code_push_protocol/lib/extensions/auth_provider.dart similarity index 74% rename from packages/shorebird_code_push_protocol/lib/src/models/auth_provider.dart rename to packages/shorebird_code_push_protocol/lib/extensions/auth_provider.dart index e07bb67c..17f6e93b 100644 --- a/packages/shorebird_code_push_protocol/lib/src/models/auth_provider.dart +++ b/packages/shorebird_code_push_protocol/lib/extensions/auth_provider.dart @@ -1,4 +1,8 @@ /// The authentication provider used to sign in the user. +/// +/// This enum is hand-written rather than generated: it classifies JWTs +/// by issuer server-side and never crosses the wire, so it is not part +/// of the OpenAPI spec. enum AuthProvider { /// The user authenticated using their Google account with our GCP project. google('Google'), diff --git a/packages/shorebird_code_push_protocol/lib/extensions/release_platform_extensions.dart b/packages/shorebird_code_push_protocol/lib/extensions/release_platform_extensions.dart new file mode 100644 index 00000000..5e3a474a --- /dev/null +++ b/packages/shorebird_code_push_protocol/lib/extensions/release_platform_extensions.dart @@ -0,0 +1,21 @@ +import 'package:shorebird_code_push_protocol/src/models/release_platform.dart'; + +/// Application-level behavior on [ReleasePlatform] that does not fit in +/// the OpenAPI schema. +extension ReleasePlatformExtensions on ReleasePlatform { + /// A display name suitable for human-facing UI (e.g. `"iOS"`, `"macOS"`). + String get displayName => switch (this) { + ReleasePlatform.android => 'Android', + ReleasePlatform.ios => 'iOS', + ReleasePlatform.linux => 'Linux', + ReleasePlatform.macos => 'macOS', + ReleasePlatform.windows => 'Windows', + }; + + /// Whether this platform supports Flutter build flavors. + bool get supportsFlavors => const { + ReleasePlatform.android, + ReleasePlatform.ios, + ReleasePlatform.macos, + }.contains(this); +} diff --git a/packages/shorebird_code_push_protocol/lib/extensions/test_helpers.dart b/packages/shorebird_code_push_protocol/lib/extensions/test_helpers.dart new file mode 100644 index 00000000..508f1af9 --- /dev/null +++ b/packages/shorebird_code_push_protocol/lib/extensions/test_helpers.dart @@ -0,0 +1,54 @@ +import 'package:meta/meta.dart'; +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; + +/// Constructs an [Organization] with arbitrary default values for testing. +/// +/// Replaces the old `Organization.forTest` factory — since [Organization] is +/// now generated from the OpenAPI spec, test-only defaults live here +/// instead of on the generated class. +@visibleForTesting +Organization organizationForTest({ + int id = 42, + String name = 'Test Organization', + OrganizationType organizationType = OrganizationType.personal, + DateTime? createdAt, + DateTime? updatedAt, +}) => Organization( + id: id, + name: name, + organizationType: organizationType, + createdAt: createdAt ?? DateTime.now(), + updatedAt: updatedAt ?? DateTime.now(), +); + +/// Constructs a [PrivateUser] with arbitrary default values for testing. +/// +/// Replaces the old `PrivateUser.forTest` factory. +@visibleForTesting +PrivateUser privateUserForTest({ + int id = 42, + String email = 'test@shorebird.dev', + String jwtIssuer = 'https://accounts.google.com', + bool hasActiveSubscription = false, + String? displayName, + String? stripeCustomerId, + int? patchOverageLimit = 0, +}) => PrivateUser( + id: id, + email: email, + jwtIssuer: jwtIssuer, + hasActiveSubscription: hasActiveSubscription, + displayName: displayName, + stripeCustomerId: stripeCustomerId, + patchOverageLimit: patchOverageLimit, +); + +/// Projects a [PrivateUser] down to a [PublicUser] (drops sensitive +/// fields). Replaces the old `PublicUser.fromPrivateUser` factory. +PublicUser publicUserFromPrivateUser(PrivateUser fullUser) { + return PublicUser( + id: fullUser.id, + email: fullUser.email, + displayName: fullUser.displayName, + ); +} diff --git a/packages/shorebird_code_push_protocol/lib/model_helpers.dart b/packages/shorebird_code_push_protocol/lib/model_helpers.dart new file mode 100644 index 00000000..b14712f0 --- /dev/null +++ b/packages/shorebird_code_push_protocol/lib/model_helpers.dart @@ -0,0 +1,47 @@ +import 'package:collection/collection.dart'; + +/// Runs [build] to construct a `fromJson`-parsed value of type [T], +/// converting any `TypeError` (e.g. an unexpected null or a cast +/// failure on a required field) into a `FormatException` that names +/// the class and includes the offending JSON. Generated `fromJson` +/// factories delegate to this so callers that catch `Exception` +/// treat malformed bodies as a parse error, not a crash. +T parseFromJson( + String className, + Map json, + T Function() build, +) { + try { + return build(); + } on TypeError catch (error) { + throw FormatException('Failed to parse $className from JSON: $error', json); + } +} + +/// Check if two nullable lists are deeply equal. +bool listsEqual(List? a, List? b) { + final deepEquals = const DeepCollectionEquality().equals; + return deepEquals(a, b); +} + +/// Check if two nullable maps are deeply equal. +bool mapsEqual(Map? a, Map? b) { + final deepEquals = const DeepCollectionEquality().equals; + return deepEquals(a, b); +} + +/// A deep hash of a nullable list — consistent with [listsEqual]. +/// Two lists that compare equal under [listsEqual] produce the same +/// hash. Null hashes to 0. +int listHash(List? list) { + if (list == null) return 0; + return const DeepCollectionEquality().hash(list); +} + +/// A deep hash of a nullable map — consistent with [mapsEqual]. +/// Two maps that compare equal under [mapsEqual] produce the same +/// hash. Null hashes to 0. +int mapHash(Map? map) { + if (map == null) return 0; + return const DeepCollectionEquality().hash(map); +} diff --git a/packages/shorebird_code_push_protocol/lib/shorebird_code_push_protocol.dart b/packages/shorebird_code_push_protocol/lib/shorebird_code_push_protocol.dart index 4a6d7934..4a6570a4 100644 --- a/packages/shorebird_code_push_protocol/lib/shorebird_code_push_protocol.dart +++ b/packages/shorebird_code_push_protocol/lib/shorebird_code_push_protocol.dart @@ -1,5 +1,63 @@ -export 'src/messages/messages.dart'; -export 'src/models/models.dart'; +/// The Shorebird CodePush protocol: models and message DTOs shared +/// between the CodePush server and the `shorebird_code_push_client`. +/// +/// Everything under `lib/src/` is generated from the public OpenAPI +/// spec by `space_gen`. Hand-written additions (extensions on generated +/// enums, test helpers) live under `lib/extensions/` and are +/// re-exported from here. +library; + +export 'package:shorebird_code_push_protocol/extensions/auth_provider.dart'; +export 'package:shorebird_code_push_protocol/extensions/release_platform_extensions.dart'; +export 'package:shorebird_code_push_protocol/extensions/test_helpers.dart'; +export 'package:shorebird_code_push_protocol/src/messages/create_app/create_app_request.dart'; +export 'package:shorebird_code_push_protocol/src/messages/create_app_collaborator/create_app_collaborator_request.dart'; +export 'package:shorebird_code_push_protocol/src/messages/create_channel/create_channel_request.dart'; +export 'package:shorebird_code_push_protocol/src/messages/create_patch/create_patch_request.dart'; +export 'package:shorebird_code_push_protocol/src/messages/create_patch/create_patch_response.dart'; +export 'package:shorebird_code_push_protocol/src/messages/create_patch_artifact/create_patch_artifact_request.dart'; +export 'package:shorebird_code_push_protocol/src/messages/create_patch_artifact/create_patch_artifact_response.dart'; +export 'package:shorebird_code_push_protocol/src/messages/create_release/create_release_request.dart'; +export 'package:shorebird_code_push_protocol/src/messages/create_release/create_release_response.dart'; +export 'package:shorebird_code_push_protocol/src/messages/create_release_artifact/create_release_artifact_request.dart'; +export 'package:shorebird_code_push_protocol/src/messages/create_release_artifact/create_release_artifact_response.dart'; +export 'package:shorebird_code_push_protocol/src/messages/create_user/create_user_request.dart'; +export 'package:shorebird_code_push_protocol/src/messages/error_response.dart'; +export 'package:shorebird_code_push_protocol/src/messages/get_apps/get_apps_response.dart'; +export 'package:shorebird_code_push_protocol/src/messages/get_gcp_download_speed_test_url/get_gcp_download_speed_test_url200_response.dart'; +export 'package:shorebird_code_push_protocol/src/messages/get_gcp_upload_speed_test_url/get_gcp_upload_speed_test_url200_response.dart'; +export 'package:shorebird_code_push_protocol/src/messages/get_organization_apps/get_organization_apps_response.dart'; +export 'package:shorebird_code_push_protocol/src/messages/get_organization_users/get_organization_users_response.dart'; +export 'package:shorebird_code_push_protocol/src/messages/get_organizations_response.dart'; +export 'package:shorebird_code_push_protocol/src/messages/get_release/get_release_response.dart'; +export 'package:shorebird_code_push_protocol/src/messages/get_release_artifacts/get_release_artifacts_response.dart'; +export 'package:shorebird_code_push_protocol/src/messages/get_release_patches/get_release_patches_response.dart'; +export 'package:shorebird_code_push_protocol/src/messages/get_releases/get_releases_response.dart'; +export 'package:shorebird_code_push_protocol/src/messages/patch_check/patch_check_request.dart'; +export 'package:shorebird_code_push_protocol/src/messages/patch_check/patch_check_response.dart'; +export 'package:shorebird_code_push_protocol/src/messages/promote_patch/promote_patch_request.dart'; +export 'package:shorebird_code_push_protocol/src/messages/update_app_collaborator/update_app_collaborator_request.dart'; +export 'package:shorebird_code_push_protocol/src/messages/update_patch/update_patch_request.dart'; +export 'package:shorebird_code_push_protocol/src/messages/update_release/update_release_request.dart'; +export 'package:shorebird_code_push_protocol/src/models/app.dart'; +export 'package:shorebird_code_push_protocol/src/models/app_collaborator_role.dart'; +export 'package:shorebird_code_push_protocol/src/models/app_metadata.dart'; +export 'package:shorebird_code_push_protocol/src/models/channel.dart'; +export 'package:shorebird_code_push_protocol/src/models/organization.dart'; +export 'package:shorebird_code_push_protocol/src/models/organization_membership.dart'; +export 'package:shorebird_code_push_protocol/src/models/organization_type.dart'; +export 'package:shorebird_code_push_protocol/src/models/organization_user.dart'; +export 'package:shorebird_code_push_protocol/src/models/patch.dart'; +export 'package:shorebird_code_push_protocol/src/models/patch_artifact.dart'; +export 'package:shorebird_code_push_protocol/src/models/patch_check_metadata.dart'; +export 'package:shorebird_code_push_protocol/src/models/private_user.dart'; +export 'package:shorebird_code_push_protocol/src/models/public_user.dart'; +export 'package:shorebird_code_push_protocol/src/models/release.dart'; +export 'package:shorebird_code_push_protocol/src/models/release_artifact.dart'; +export 'package:shorebird_code_push_protocol/src/models/release_patch.dart'; +export 'package:shorebird_code_push_protocol/src/models/release_platform.dart'; +export 'package:shorebird_code_push_protocol/src/models/release_status.dart'; +export 'package:shorebird_code_push_protocol/src/models/role.dart'; /// Parsed JSON data. typedef Json = Map; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/create_app/create_app.dart b/packages/shorebird_code_push_protocol/lib/src/messages/create_app/create_app.dart deleted file mode 100644 index 2541baec..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/create_app/create_app.dart +++ /dev/null @@ -1 +0,0 @@ -export 'create_app_request.dart'; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/create_app/create_app_request.dart b/packages/shorebird_code_push_protocol/lib/src/messages/create_app/create_app_request.dart index 96ea66aa..baf8e476 100644 --- a/packages/shorebird_code_push_protocol/lib/src/messages/create_app/create_app_request.dart +++ b/packages/shorebird_code_push_protocol/lib/src/messages/create_app/create_app_request.dart @@ -1,11 +1,10 @@ -import 'package:json_annotation/json_annotation.dart'; - -part 'create_app_request.g.dart'; +import 'package:meta/meta.dart'; +import 'package:shorebird_code_push_protocol/model_helpers.dart'; /// {@template create_app_request} -/// The request body for POST /api/v1/apps +/// The request body for POST /apps. /// {@endtemplate} -@JsonSerializable() +@immutable class CreateAppRequest { /// {@macro create_app_request} const CreateAppRequest({ @@ -13,16 +12,52 @@ class CreateAppRequest { required this.organizationId, }); - /// Converts a `Map` to a [CreateAppRequest] - factory CreateAppRequest.fromJson(Map json) => - _$CreateAppRequestFromJson(json); + /// Converts a `Map` to a [CreateAppRequest]. + factory CreateAppRequest.fromJson(Map json) { + return parseFromJson( + 'CreateAppRequest', + json, + () => CreateAppRequest( + displayName: json['display_name'] as String, + organizationId: json['organization_id'] as int, + ), + ); + } - /// Converts a [CreateAppRequest] to a `Map` - Map toJson() => _$CreateAppRequestToJson(this); + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static CreateAppRequest? maybeFromJson(Map? json) { + if (json == null) { + return null; + } + return CreateAppRequest.fromJson(json); + } /// The display name of the app. final String displayName; /// The id of organization that this app will belong to. final int organizationId; + + /// Converts a [CreateAppRequest] to a `Map`. + Map toJson() { + return { + 'display_name': displayName, + 'organization_id': organizationId, + }; + } + + @override + int get hashCode => Object.hashAll([ + displayName, + organizationId, + ]); + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is CreateAppRequest && + displayName == other.displayName && + organizationId == other.organizationId; + } } diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/create_app/create_app_request.g.dart b/packages/shorebird_code_push_protocol/lib/src/messages/create_app/create_app_request.g.dart deleted file mode 100644 index cfc68bac..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/create_app/create_app_request.g.dart +++ /dev/null @@ -1,35 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ignore_for_file: implicit_dynamic_parameter, require_trailing_commas, cast_nullable_to_non_nullable, lines_longer_than_80_chars - -part of 'create_app_request.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -CreateAppRequest _$CreateAppRequestFromJson(Map json) => - $checkedCreate( - 'CreateAppRequest', - json, - ($checkedConvert) { - final val = CreateAppRequest( - displayName: $checkedConvert('display_name', (v) => v as String), - organizationId: $checkedConvert( - 'organization_id', - (v) => (v as num).toInt(), - ), - ); - return val; - }, - fieldKeyMap: const { - 'displayName': 'display_name', - 'organizationId': 'organization_id', - }, - ); - -Map _$CreateAppRequestToJson(CreateAppRequest instance) => - { - 'display_name': instance.displayName, - 'organization_id': instance.organizationId, - }; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/create_app_collaborator/create_app_collaborator.dart b/packages/shorebird_code_push_protocol/lib/src/messages/create_app_collaborator/create_app_collaborator.dart deleted file mode 100644 index a2ec90be..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/create_app_collaborator/create_app_collaborator.dart +++ /dev/null @@ -1 +0,0 @@ -export 'create_app_collaborator_request.dart'; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/create_app_collaborator/create_app_collaborator_request.dart b/packages/shorebird_code_push_protocol/lib/src/messages/create_app_collaborator/create_app_collaborator_request.dart index 5c3ab75e..448a2c5f 100644 --- a/packages/shorebird_code_push_protocol/lib/src/messages/create_app_collaborator/create_app_collaborator_request.dart +++ b/packages/shorebird_code_push_protocol/lib/src/messages/create_app_collaborator/create_app_collaborator_request.dart @@ -1,22 +1,54 @@ -import 'package:json_annotation/json_annotation.dart'; - -part 'create_app_collaborator_request.g.dart'; +import 'package:meta/meta.dart'; +import 'package:shorebird_code_push_protocol/model_helpers.dart'; /// {@template create_app_collaborator_request} -/// The request body for POST /api/v1/apps/:id/collaborators +/// The request body for POST /apps/{appId}/collaborators. /// {@endtemplate} -@JsonSerializable() +@immutable class CreateAppCollaboratorRequest { /// {@macro create_app_collaborator_request} - const CreateAppCollaboratorRequest({required this.email}); + const CreateAppCollaboratorRequest({ + required this.email, + }); - /// Converts a `Map` to a [CreateAppCollaboratorRequest] - factory CreateAppCollaboratorRequest.fromJson(Map json) => - _$CreateAppCollaboratorRequestFromJson(json); + /// Converts a `Map` to a [CreateAppCollaboratorRequest]. + factory CreateAppCollaboratorRequest.fromJson(Map json) { + return parseFromJson( + 'CreateAppCollaboratorRequest', + json, + () => CreateAppCollaboratorRequest( + email: json['email'] as String, + ), + ); + } - /// Converts a [CreateAppCollaboratorRequest] to a `Map` - Map toJson() => _$CreateAppCollaboratorRequestToJson(this); + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static CreateAppCollaboratorRequest? maybeFromJson( + Map? json, + ) { + if (json == null) { + return null; + } + return CreateAppCollaboratorRequest.fromJson(json); + } /// The email of the collaborator to add. final String email; + + /// Converts a [CreateAppCollaboratorRequest] to a `Map`. + Map toJson() { + return { + 'email': email, + }; + } + + @override + int get hashCode => email.hashCode; + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is CreateAppCollaboratorRequest && email == other.email; + } } diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/create_app_collaborator/create_app_collaborator_request.g.dart b/packages/shorebird_code_push_protocol/lib/src/messages/create_app_collaborator/create_app_collaborator_request.g.dart deleted file mode 100644 index 5cceb5cd..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/create_app_collaborator/create_app_collaborator_request.g.dart +++ /dev/null @@ -1,22 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ignore_for_file: implicit_dynamic_parameter, require_trailing_commas, cast_nullable_to_non_nullable, lines_longer_than_80_chars - -part of 'create_app_collaborator_request.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -CreateAppCollaboratorRequest _$CreateAppCollaboratorRequestFromJson( - Map json, -) => $checkedCreate('CreateAppCollaboratorRequest', json, ($checkedConvert) { - final val = CreateAppCollaboratorRequest( - email: $checkedConvert('email', (v) => v as String), - ); - return val; -}); - -Map _$CreateAppCollaboratorRequestToJson( - CreateAppCollaboratorRequest instance, -) => {'email': instance.email}; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/create_channel/create_channel.dart b/packages/shorebird_code_push_protocol/lib/src/messages/create_channel/create_channel.dart deleted file mode 100644 index 9344be4d..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/create_channel/create_channel.dart +++ /dev/null @@ -1 +0,0 @@ -export 'create_channel_request.dart'; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/create_channel/create_channel_request.dart b/packages/shorebird_code_push_protocol/lib/src/messages/create_channel/create_channel_request.dart index 8924b2c8..a14fe4e1 100644 --- a/packages/shorebird_code_push_protocol/lib/src/messages/create_channel/create_channel_request.dart +++ b/packages/shorebird_code_push_protocol/lib/src/messages/create_channel/create_channel_request.dart @@ -1,22 +1,52 @@ -import 'package:json_annotation/json_annotation.dart'; - -part 'create_channel_request.g.dart'; +import 'package:meta/meta.dart'; +import 'package:shorebird_code_push_protocol/model_helpers.dart'; /// {@template create_channel_request} -/// The request body for POST /api/v1/apps/:appId/channels +/// The request body for POST /apps/{appId}/channels. /// {@endtemplate} -@JsonSerializable() +@immutable class CreateChannelRequest { /// {@macro create_channel_request} - const CreateChannelRequest({required this.channel}); + const CreateChannelRequest({ + required this.channel, + }); - /// Converts a `Map` to a [CreateChannelRequest] - factory CreateChannelRequest.fromJson(Map json) => - _$CreateChannelRequestFromJson(json); + /// Converts a `Map` to a [CreateChannelRequest]. + factory CreateChannelRequest.fromJson(Map json) { + return parseFromJson( + 'CreateChannelRequest', + json, + () => CreateChannelRequest( + channel: json['channel'] as String, + ), + ); + } - /// Converts a [CreateChannelRequest] to a `Map` - Map toJson() => _$CreateChannelRequestToJson(this); + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static CreateChannelRequest? maybeFromJson(Map? json) { + if (json == null) { + return null; + } + return CreateChannelRequest.fromJson(json); + } /// The channel name. final String channel; + + /// Converts a [CreateChannelRequest] to a `Map`. + Map toJson() { + return { + 'channel': channel, + }; + } + + @override + int get hashCode => channel.hashCode; + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is CreateChannelRequest && channel == other.channel; + } } diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/create_channel/create_channel_request.g.dart b/packages/shorebird_code_push_protocol/lib/src/messages/create_channel/create_channel_request.g.dart deleted file mode 100644 index 644c566d..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/create_channel/create_channel_request.g.dart +++ /dev/null @@ -1,22 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ignore_for_file: implicit_dynamic_parameter, require_trailing_commas, cast_nullable_to_non_nullable, lines_longer_than_80_chars - -part of 'create_channel_request.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -CreateChannelRequest _$CreateChannelRequestFromJson( - Map json, -) => $checkedCreate('CreateChannelRequest', json, ($checkedConvert) { - final val = CreateChannelRequest( - channel: $checkedConvert('channel', (v) => v as String), - ); - return val; -}); - -Map _$CreateChannelRequestToJson( - CreateChannelRequest instance, -) => {'channel': instance.channel}; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/create_patch/create_patch.dart b/packages/shorebird_code_push_protocol/lib/src/messages/create_patch/create_patch.dart deleted file mode 100644 index e70edf05..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/create_patch/create_patch.dart +++ /dev/null @@ -1,2 +0,0 @@ -export 'create_patch_request.dart'; -export 'create_patch_response.dart'; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/create_patch/create_patch_request.dart b/packages/shorebird_code_push_protocol/lib/src/messages/create_patch/create_patch_request.dart index 40419d31..c36a3f23 100644 --- a/packages/shorebird_code_push_protocol/lib/src/messages/create_patch/create_patch_request.dart +++ b/packages/shorebird_code_push_protocol/lib/src/messages/create_patch/create_patch_request.dart @@ -1,27 +1,66 @@ -import 'package:json_annotation/json_annotation.dart'; -import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; - -part 'create_patch_request.g.dart'; +import 'package:meta/meta.dart'; +import 'package:shorebird_code_push_protocol/model_helpers.dart'; /// {@template create_patch_request} -/// The request body for POST /api/v1/patches +/// The request body for POST /apps/{appId}/patches. /// {@endtemplate} -@JsonSerializable() +@immutable class CreatePatchRequest { /// {@macro create_patch_request} - const CreatePatchRequest({required this.releaseId, required this.metadata}); + const CreatePatchRequest({ + required this.releaseId, + required this.metadata, + }); - /// Converts a `Map` to a [CreatePatchRequest] - factory CreatePatchRequest.fromJson(Map json) => - _$CreatePatchRequestFromJson(json); + /// Converts a `Map` to a [CreatePatchRequest]. + factory CreatePatchRequest.fromJson(Map json) { + return parseFromJson( + 'CreatePatchRequest', + json, + () => CreatePatchRequest( + releaseId: json['release_id'] as int, + metadata: (json['metadata'] as Map).map( + MapEntry.new, + ), + ), + ); + } - /// Converts a [CreatePatchRequest] to a `Map` - Map toJson() => _$CreatePatchRequestToJson(this); + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static CreatePatchRequest? maybeFromJson(Map? json) { + if (json == null) { + return null; + } + return CreatePatchRequest.fromJson(json); + } /// The ID of the release. final int releaseId; - /// Additional information about the command that was run to create the patch - /// and the environment in which it was run. - final Json metadata; + /// Additional information about the command that was run to + /// create the patch and the environment it was run in. + final Map metadata; + + /// Converts a [CreatePatchRequest] to a `Map`. + Map toJson() { + return { + 'release_id': releaseId, + 'metadata': metadata, + }; + } + + @override + int get hashCode => Object.hashAll([ + releaseId, + mapHash(metadata), + ]); + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is CreatePatchRequest && + releaseId == other.releaseId && + mapsEqual(metadata, other.metadata); + } } diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/create_patch/create_patch_request.g.dart b/packages/shorebird_code_push_protocol/lib/src/messages/create_patch/create_patch_request.g.dart deleted file mode 100644 index fa62cc25..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/create_patch/create_patch_request.g.dart +++ /dev/null @@ -1,24 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ignore_for_file: implicit_dynamic_parameter, require_trailing_commas, cast_nullable_to_non_nullable, lines_longer_than_80_chars - -part of 'create_patch_request.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -CreatePatchRequest _$CreatePatchRequestFromJson(Map json) => - $checkedCreate('CreatePatchRequest', json, ($checkedConvert) { - final val = CreatePatchRequest( - releaseId: $checkedConvert('release_id', (v) => (v as num).toInt()), - metadata: $checkedConvert('metadata', (v) => v as Map), - ); - return val; - }, fieldKeyMap: const {'releaseId': 'release_id'}); - -Map _$CreatePatchRequestToJson(CreatePatchRequest instance) => - { - 'release_id': instance.releaseId, - 'metadata': instance.metadata, - }; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/create_patch/create_patch_response.dart b/packages/shorebird_code_push_protocol/lib/src/messages/create_patch/create_patch_response.dart index 2dbf374d..6490e938 100644 --- a/packages/shorebird_code_push_protocol/lib/src/messages/create_patch/create_patch_response.dart +++ b/packages/shorebird_code_push_protocol/lib/src/messages/create_patch/create_patch_response.dart @@ -1,26 +1,70 @@ -import 'package:json_annotation/json_annotation.dart'; - -part 'create_patch_response.g.dart'; +import 'package:meta/meta.dart'; +import 'package:shorebird_code_push_protocol/model_helpers.dart'; +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart' + show Patch; +import 'package:shorebird_code_push_protocol/src/models/patch.dart' show Patch; /// {@template create_patch_response} -/// The response body for POST /api/v1/patches +/// The response body for POST /apps/{appId}/patches. Deliberately +/// narrower than [Patch]: a freshly-created patch has no `notes` +/// yet (those are set via PATCH /.../{patchId}), so this endpoint +/// exposes only the identifiers the client needs to upload +/// artifacts. /// {@endtemplate} -@JsonSerializable() +@immutable class CreatePatchResponse { /// {@macro create_patch_response} - const CreatePatchResponse({required this.id, required this.number}); + const CreatePatchResponse({ + required this.id, + required this.number, + }); - /// Converts a `Map` to a [CreatePatchResponse] - factory CreatePatchResponse.fromJson(Map json) => - _$CreatePatchResponseFromJson(json); + /// Converts a `Map` to a [CreatePatchResponse]. + factory CreatePatchResponse.fromJson(Map json) { + return parseFromJson( + 'CreatePatchResponse', + json, + () => CreatePatchResponse( + id: json['id'] as int, + number: json['number'] as int, + ), + ); + } - /// Converts a [CreatePatchResponse] to a `Map` - Map toJson() => _$CreatePatchResponseToJson(this); + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static CreatePatchResponse? maybeFromJson(Map? json) { + if (json == null) { + return null; + } + return CreatePatchResponse.fromJson(json); + } /// The unique patch identifier. final int id; - /// The patch number. - /// A larger number equates to a newer patch. + /// The patch number. A larger number equates to a newer patch. final int number; + + /// Converts a [CreatePatchResponse] to a `Map`. + Map toJson() { + return { + 'id': id, + 'number': number, + }; + } + + @override + int get hashCode => Object.hashAll([ + id, + number, + ]); + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is CreatePatchResponse && + id == other.id && + number == other.number; + } } diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/create_patch/create_patch_response.g.dart b/packages/shorebird_code_push_protocol/lib/src/messages/create_patch/create_patch_response.g.dart deleted file mode 100644 index e9c05195..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/create_patch/create_patch_response.g.dart +++ /dev/null @@ -1,22 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ignore_for_file: implicit_dynamic_parameter, require_trailing_commas, cast_nullable_to_non_nullable, lines_longer_than_80_chars - -part of 'create_patch_response.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -CreatePatchResponse _$CreatePatchResponseFromJson(Map json) => - $checkedCreate('CreatePatchResponse', json, ($checkedConvert) { - final val = CreatePatchResponse( - id: $checkedConvert('id', (v) => (v as num).toInt()), - number: $checkedConvert('number', (v) => (v as num).toInt()), - ); - return val; - }); - -Map _$CreatePatchResponseToJson( - CreatePatchResponse instance, -) => {'id': instance.id, 'number': instance.number}; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/create_patch_artifact/create_patch_artifact.dart b/packages/shorebird_code_push_protocol/lib/src/messages/create_patch_artifact/create_patch_artifact.dart deleted file mode 100644 index 31a75e46..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/create_patch_artifact/create_patch_artifact.dart +++ /dev/null @@ -1,2 +0,0 @@ -export 'create_patch_artifact_request.dart'; -export 'create_patch_artifact_response.dart'; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/create_patch_artifact/create_patch_artifact_request.dart b/packages/shorebird_code_push_protocol/lib/src/messages/create_patch_artifact/create_patch_artifact_request.dart index cfb9b59c..ae9ebca6 100644 --- a/packages/shorebird_code_push_protocol/lib/src/messages/create_patch_artifact/create_patch_artifact_request.dart +++ b/packages/shorebird_code_push_protocol/lib/src/messages/create_patch_artifact/create_patch_artifact_request.dart @@ -1,14 +1,15 @@ -import 'package:json_annotation/json_annotation.dart'; -import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; - -part 'create_patch_artifact_request.g.dart'; +import 'package:meta/meta.dart'; +import 'package:shorebird_code_push_protocol/model_helpers.dart'; +import 'package:shorebird_code_push_protocol/src/models/release_platform.dart'; /// {@template create_patch_artifact_request} -/// The request body for POST /api/v1/patches/:id/artifacts +/// Metadata for a new patch artifact. POST to +/// /apps/{appId}/patches/{patchId}/artifacts and use the returned +/// signed upload URL to upload the artifact bytes separately. /// {@endtemplate} -@JsonSerializable() +@immutable class CreatePatchArtifactRequest { - /// {@macro create_artifact_request} + /// {@macro create_patch_artifact_request} const CreatePatchArtifactRequest({ required this.arch, required this.platform, @@ -18,27 +19,43 @@ class CreatePatchArtifactRequest { this.podfileLockHash, }); - /// Converts a `Map` to a [CreatePatchArtifactRequest] - factory CreatePatchArtifactRequest.fromJson(Map json) => - _$CreatePatchArtifactRequestFromJson(json); + /// Converts a `Map` to a [CreatePatchArtifactRequest]. + factory CreatePatchArtifactRequest.fromJson(Map json) { + return parseFromJson( + 'CreatePatchArtifactRequest', + json, + () => CreatePatchArtifactRequest( + arch: json['arch'] as String, + platform: ReleasePlatform.fromJson(json['platform'] as String), + hash: json['hash'] as String, + hashSignature: json['hash_signature'] as String?, + podfileLockHash: json['podfile_lock_hash'] as String?, + size: json['size'] as int, + ), + ); + } - /// Converts a [CreatePatchArtifactRequest] to a `Map`. - Json toJson() => _$CreatePatchArtifactRequestToJson(this); + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static CreatePatchArtifactRequest? maybeFromJson(Map? json) { + if (json == null) { + return null; + } + return CreatePatchArtifactRequest.fromJson(json); + } /// The arch of the artifact. final String arch; - /// The platform of the artifact. + /// A platform to which a Shorebird release can be deployed. final ReleasePlatform platform; /// The hash of the artifact. final String hash; - /// The signature of the [hash]. - /// - /// Patch code signing is an opt in feature, introduced later in the life of - /// the product, so when this field is null, the patch does not uses code - /// signing. + /// The signature of the [hash]. Patch code signing is an opt in feature, + /// introduced later in the life of the product, so when this field is null, + /// the patch does not uses code signing. final String? hashSignature; /// The sha256 hash of the Podfile.lock file, if a Podfile.lock file was @@ -46,10 +63,39 @@ class CreatePatchArtifactRequest { final String? podfileLockHash; /// The size of the artifact in bytes. - @JsonKey(fromJson: _parseStringToInt, toJson: _parseIntToString) final int size; - static int _parseStringToInt(dynamic value) => int.parse(value as String); + /// Converts a [CreatePatchArtifactRequest] to a `Map`. + Map toJson() { + return { + 'arch': arch, + 'platform': platform.toJson(), + 'hash': hash, + 'hash_signature': hashSignature, + 'podfile_lock_hash': podfileLockHash, + 'size': size, + }; + } - static String _parseIntToString(dynamic value) => value.toString(); + @override + int get hashCode => Object.hashAll([ + arch, + platform, + hash, + hashSignature, + podfileLockHash, + size, + ]); + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is CreatePatchArtifactRequest && + arch == other.arch && + platform == other.platform && + hash == other.hash && + hashSignature == other.hashSignature && + podfileLockHash == other.podfileLockHash && + size == other.size; + } } diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/create_patch_artifact/create_patch_artifact_request.g.dart b/packages/shorebird_code_push_protocol/lib/src/messages/create_patch_artifact/create_patch_artifact_request.g.dart deleted file mode 100644 index 14d4bac2..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/create_patch_artifact/create_patch_artifact_request.g.dart +++ /dev/null @@ -1,59 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ignore_for_file: implicit_dynamic_parameter, require_trailing_commas, cast_nullable_to_non_nullable, lines_longer_than_80_chars - -part of 'create_patch_artifact_request.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -CreatePatchArtifactRequest _$CreatePatchArtifactRequestFromJson( - Map json, -) => $checkedCreate( - 'CreatePatchArtifactRequest', - json, - ($checkedConvert) { - final val = CreatePatchArtifactRequest( - arch: $checkedConvert('arch', (v) => v as String), - platform: $checkedConvert( - 'platform', - (v) => $enumDecode(_$ReleasePlatformEnumMap, v), - ), - hash: $checkedConvert('hash', (v) => v as String), - size: $checkedConvert( - 'size', - (v) => CreatePatchArtifactRequest._parseStringToInt(v), - ), - hashSignature: $checkedConvert('hash_signature', (v) => v as String?), - podfileLockHash: $checkedConvert( - 'podfile_lock_hash', - (v) => v as String?, - ), - ); - return val; - }, - fieldKeyMap: const { - 'hashSignature': 'hash_signature', - 'podfileLockHash': 'podfile_lock_hash', - }, -); - -Map _$CreatePatchArtifactRequestToJson( - CreatePatchArtifactRequest instance, -) => { - 'arch': instance.arch, - 'platform': _$ReleasePlatformEnumMap[instance.platform]!, - 'hash': instance.hash, - 'hash_signature': instance.hashSignature, - 'podfile_lock_hash': instance.podfileLockHash, - 'size': CreatePatchArtifactRequest._parseIntToString(instance.size), -}; - -const _$ReleasePlatformEnumMap = { - ReleasePlatform.android: 'android', - ReleasePlatform.ios: 'ios', - ReleasePlatform.linux: 'linux', - ReleasePlatform.macos: 'macos', - ReleasePlatform.windows: 'windows', -}; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/create_patch_artifact/create_patch_artifact_response.dart b/packages/shorebird_code_push_protocol/lib/src/messages/create_patch_artifact/create_patch_artifact_response.dart index a2ae8194..ba8e102c 100644 --- a/packages/shorebird_code_push_protocol/lib/src/messages/create_patch_artifact/create_patch_artifact_response.dart +++ b/packages/shorebird_code_push_protocol/lib/src/messages/create_patch_artifact/create_patch_artifact_response.dart @@ -1,14 +1,13 @@ -import 'package:json_annotation/json_annotation.dart'; -import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; - -part 'create_patch_artifact_response.g.dart'; +import 'package:meta/meta.dart'; +import 'package:shorebird_code_push_protocol/model_helpers.dart'; +import 'package:shorebird_code_push_protocol/src/models/release_platform.dart'; /// {@template create_patch_artifact_response} -/// The response body for POST /api/v1/patches/:id/artifacts +/// The response body for registering a patch artifact. /// {@endtemplate} -@JsonSerializable() +@immutable class CreatePatchArtifactResponse { - /// {@macro create_artifact_response} + /// {@macro create_patch_artifact_response} const CreatePatchArtifactResponse({ required this.id, required this.patchId, @@ -19,14 +18,35 @@ class CreatePatchArtifactResponse { required this.url, }); - /// Converts a `Map` to a [CreatePatchArtifactResponse] - factory CreatePatchArtifactResponse.fromJson(Map json) => - _$CreatePatchArtifactResponseFromJson(json); + /// Converts a `Map` to a [CreatePatchArtifactResponse]. + factory CreatePatchArtifactResponse.fromJson(Map json) { + return parseFromJson( + 'CreatePatchArtifactResponse', + json, + () => CreatePatchArtifactResponse( + id: json['id'] as int, + patchId: json['patch_id'] as int, + arch: json['arch'] as String, + platform: ReleasePlatform.fromJson(json['platform'] as String), + hash: json['hash'] as String, + size: json['size'] as int, + url: json['url'] as String, + ), + ); + } - /// Converts a [CreatePatchArtifactResponse] to a `Map`. - Json toJson() => _$CreatePatchArtifactResponseToJson(this); + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static CreatePatchArtifactResponse? maybeFromJson( + Map? json, + ) { + if (json == null) { + return null; + } + return CreatePatchArtifactResponse.fromJson(json); + } - /// The ID of the artifact; + /// The ID of the artifact. final int id; /// The ID of the patch. @@ -35,7 +55,7 @@ class CreatePatchArtifactResponse { /// The arch of the artifact. final String arch; - /// The platform of the artifact. + /// A platform to which a Shorebird release can be deployed. final ReleasePlatform platform; /// The hash of the artifact. @@ -46,4 +66,41 @@ class CreatePatchArtifactResponse { /// The upload URL for the artifact. final String url; + + /// Converts a [CreatePatchArtifactResponse] to a `Map`. + Map toJson() { + return { + 'id': id, + 'patch_id': patchId, + 'arch': arch, + 'platform': platform.toJson(), + 'hash': hash, + 'size': size, + 'url': url, + }; + } + + @override + int get hashCode => Object.hashAll([ + id, + patchId, + arch, + platform, + hash, + size, + url, + ]); + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is CreatePatchArtifactResponse && + id == other.id && + patchId == other.patchId && + arch == other.arch && + platform == other.platform && + hash == other.hash && + size == other.size && + url == other.url; + } } diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/create_patch_artifact/create_patch_artifact_response.g.dart b/packages/shorebird_code_push_protocol/lib/src/messages/create_patch_artifact/create_patch_artifact_response.g.dart deleted file mode 100644 index 8c041d61..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/create_patch_artifact/create_patch_artifact_response.g.dart +++ /dev/null @@ -1,47 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ignore_for_file: implicit_dynamic_parameter, require_trailing_commas, cast_nullable_to_non_nullable, lines_longer_than_80_chars - -part of 'create_patch_artifact_response.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -CreatePatchArtifactResponse _$CreatePatchArtifactResponseFromJson( - Map json, -) => $checkedCreate('CreatePatchArtifactResponse', json, ($checkedConvert) { - final val = CreatePatchArtifactResponse( - id: $checkedConvert('id', (v) => (v as num).toInt()), - patchId: $checkedConvert('patch_id', (v) => (v as num).toInt()), - arch: $checkedConvert('arch', (v) => v as String), - platform: $checkedConvert( - 'platform', - (v) => $enumDecode(_$ReleasePlatformEnumMap, v), - ), - hash: $checkedConvert('hash', (v) => v as String), - size: $checkedConvert('size', (v) => (v as num).toInt()), - url: $checkedConvert('url', (v) => v as String), - ); - return val; -}, fieldKeyMap: const {'patchId': 'patch_id'}); - -Map _$CreatePatchArtifactResponseToJson( - CreatePatchArtifactResponse instance, -) => { - 'id': instance.id, - 'patch_id': instance.patchId, - 'arch': instance.arch, - 'platform': _$ReleasePlatformEnumMap[instance.platform]!, - 'hash': instance.hash, - 'size': instance.size, - 'url': instance.url, -}; - -const _$ReleasePlatformEnumMap = { - ReleasePlatform.android: 'android', - ReleasePlatform.ios: 'ios', - ReleasePlatform.linux: 'linux', - ReleasePlatform.macos: 'macos', - ReleasePlatform.windows: 'windows', -}; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/create_release/create_release.dart b/packages/shorebird_code_push_protocol/lib/src/messages/create_release/create_release.dart deleted file mode 100644 index 37906ffb..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/create_release/create_release.dart +++ /dev/null @@ -1,2 +0,0 @@ -export 'create_release_request.dart'; -export 'create_release_response.dart'; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/create_release/create_release_request.dart b/packages/shorebird_code_push_protocol/lib/src/messages/create_release/create_release_request.dart index 5ce72217..95f54a41 100644 --- a/packages/shorebird_code_push_protocol/lib/src/messages/create_release/create_release_request.dart +++ b/packages/shorebird_code_push_protocol/lib/src/messages/create_release/create_release_request.dart @@ -1,26 +1,41 @@ -import 'package:json_annotation/json_annotation.dart'; - -part 'create_release_request.g.dart'; +import 'package:meta/meta.dart'; +import 'package:shorebird_code_push_protocol/model_helpers.dart'; /// {@template create_release_request} -/// The request body for POST /api/v1/apps/:appId/releases +/// The request body for POST /apps/{appId}/releases. /// {@endtemplate} -@JsonSerializable() +@immutable class CreateReleaseRequest { /// {@macro create_release_request} const CreateReleaseRequest({ required this.version, required this.flutterRevision, - required this.flutterVersion, + this.flutterVersion, this.displayName, }); - /// Converts a `Map` to a [CreateReleaseRequest] - factory CreateReleaseRequest.fromJson(Map json) => - _$CreateReleaseRequestFromJson(json); + /// Converts a `Map` to a [CreateReleaseRequest]. + factory CreateReleaseRequest.fromJson(Map json) { + return parseFromJson( + 'CreateReleaseRequest', + json, + () => CreateReleaseRequest( + version: json['version'] as String, + flutterRevision: json['flutter_revision'] as String, + flutterVersion: json['flutter_version'] as String?, + displayName: json['display_name'] as String?, + ), + ); + } - /// Converts a [CreateReleaseRequest] to a `Map` - Map toJson() => _$CreateReleaseRequestToJson(this); + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static CreateReleaseRequest? maybeFromJson(Map? json) { + if (json == null) { + return null; + } + return CreateReleaseRequest.fromJson(json); + } /// The release version. final String version; @@ -28,12 +43,39 @@ class CreateReleaseRequest { /// The Flutter revision used to create the release. final String flutterRevision; - /// The Flutter version used to create the release. - /// - /// This field is optional because it was newly added and - /// older releases do not have this information. + /// The Flutter version used to create the release. This field is optional + /// because it was newly added and older releases do not have this + /// information. final String? flutterVersion; /// The display name for the release. final String? displayName; + + /// Converts a [CreateReleaseRequest] to a `Map`. + Map toJson() { + return { + 'version': version, + 'flutter_revision': flutterRevision, + 'flutter_version': flutterVersion, + 'display_name': displayName, + }; + } + + @override + int get hashCode => Object.hashAll([ + version, + flutterRevision, + flutterVersion, + displayName, + ]); + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is CreateReleaseRequest && + version == other.version && + flutterRevision == other.flutterRevision && + flutterVersion == other.flutterVersion && + displayName == other.displayName; + } } diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/create_release/create_release_request.g.dart b/packages/shorebird_code_push_protocol/lib/src/messages/create_release/create_release_request.g.dart deleted file mode 100644 index 65ed1fa3..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/create_release/create_release_request.g.dart +++ /dev/null @@ -1,39 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ignore_for_file: implicit_dynamic_parameter, require_trailing_commas, cast_nullable_to_non_nullable, lines_longer_than_80_chars - -part of 'create_release_request.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -CreateReleaseRequest _$CreateReleaseRequestFromJson( - Map json, -) => $checkedCreate( - 'CreateReleaseRequest', - json, - ($checkedConvert) { - final val = CreateReleaseRequest( - version: $checkedConvert('version', (v) => v as String), - flutterRevision: $checkedConvert('flutter_revision', (v) => v as String), - flutterVersion: $checkedConvert('flutter_version', (v) => v as String?), - displayName: $checkedConvert('display_name', (v) => v as String?), - ); - return val; - }, - fieldKeyMap: const { - 'flutterRevision': 'flutter_revision', - 'flutterVersion': 'flutter_version', - 'displayName': 'display_name', - }, -); - -Map _$CreateReleaseRequestToJson( - CreateReleaseRequest instance, -) => { - 'version': instance.version, - 'flutter_revision': instance.flutterRevision, - 'flutter_version': instance.flutterVersion, - 'display_name': instance.displayName, -}; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/create_release/create_release_response.dart b/packages/shorebird_code_push_protocol/lib/src/messages/create_release/create_release_response.dart index 02a48190..3fe7f50f 100644 --- a/packages/shorebird_code_push_protocol/lib/src/messages/create_release/create_release_response.dart +++ b/packages/shorebird_code_push_protocol/lib/src/messages/create_release/create_release_response.dart @@ -1,23 +1,54 @@ -import 'package:json_annotation/json_annotation.dart'; -import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; - -part 'create_release_response.g.dart'; +import 'package:meta/meta.dart'; +import 'package:shorebird_code_push_protocol/model_helpers.dart'; +import 'package:shorebird_code_push_protocol/src/models/release.dart'; /// {@template create_release_response} -/// The response body for POST /api/v1/apps/:appId/releases +/// The response body for POST /apps/{appId}/releases. /// {@endtemplate} -@JsonSerializable() +@immutable class CreateReleaseResponse { /// {@macro create_release_response} - const CreateReleaseResponse({required this.release}); + const CreateReleaseResponse({ + required this.release, + }); - /// Converts a `Map` to a [CreateReleaseResponse] - factory CreateReleaseResponse.fromJson(Map json) => - _$CreateReleaseResponseFromJson(json); + /// Converts a `Map` to a [CreateReleaseResponse]. + factory CreateReleaseResponse.fromJson(Map json) { + return parseFromJson( + 'CreateReleaseResponse', + json, + () => CreateReleaseResponse( + release: Release.fromJson(json['release'] as Map), + ), + ); + } - /// Converts a [CreateReleaseResponse] to a `Map` - Map toJson() => _$CreateReleaseResponseToJson(this); + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static CreateReleaseResponse? maybeFromJson(Map? json) { + if (json == null) { + return null; + } + return CreateReleaseResponse.fromJson(json); + } - /// The newly-created release. + /// A release build of an application that is distributed to devices. + /// A release can have zero or more patches applied to it. final Release release; + + /// Converts a [CreateReleaseResponse] to a `Map`. + Map toJson() { + return { + 'release': release.toJson(), + }; + } + + @override + int get hashCode => release.hashCode; + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is CreateReleaseResponse && release == other.release; + } } diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/create_release/create_release_response.g.dart b/packages/shorebird_code_push_protocol/lib/src/messages/create_release/create_release_response.g.dart deleted file mode 100644 index d28682f2..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/create_release/create_release_response.g.dart +++ /dev/null @@ -1,25 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ignore_for_file: implicit_dynamic_parameter, require_trailing_commas, cast_nullable_to_non_nullable, lines_longer_than_80_chars - -part of 'create_release_response.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -CreateReleaseResponse _$CreateReleaseResponseFromJson( - Map json, -) => $checkedCreate('CreateReleaseResponse', json, ($checkedConvert) { - final val = CreateReleaseResponse( - release: $checkedConvert( - 'release', - (v) => Release.fromJson(v as Map), - ), - ); - return val; -}); - -Map _$CreateReleaseResponseToJson( - CreateReleaseResponse instance, -) => {'release': instance.release.toJson()}; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/create_release_artifact/create_release_artifact.dart b/packages/shorebird_code_push_protocol/lib/src/messages/create_release_artifact/create_release_artifact.dart deleted file mode 100644 index fb12714b..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/create_release_artifact/create_release_artifact.dart +++ /dev/null @@ -1,2 +0,0 @@ -export 'create_release_artifact_request.dart'; -export 'create_release_artifact_response.dart'; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/create_release_artifact/create_release_artifact_request.dart b/packages/shorebird_code_push_protocol/lib/src/messages/create_release_artifact/create_release_artifact_request.dart index 9dda5f6e..9dbd32f3 100644 --- a/packages/shorebird_code_push_protocol/lib/src/messages/create_release_artifact/create_release_artifact_request.dart +++ b/packages/shorebird_code_push_protocol/lib/src/messages/create_release_artifact/create_release_artifact_request.dart @@ -1,38 +1,58 @@ -import 'package:json_annotation/json_annotation.dart'; -import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; - -part 'create_release_artifact_request.g.dart'; +import 'package:meta/meta.dart'; +import 'package:shorebird_code_push_protocol/model_helpers.dart'; +import 'package:shorebird_code_push_protocol/src/models/release_platform.dart'; /// {@template create_release_artifact_request} -/// The request body for POST /api/v1/artifacts/:id/artifacts -/// -/// Because this request is sent as a http.MultipartRequest, all fields -/// serialize to strings. +/// Metadata for a new release artifact. POST to +/// /apps/{appId}/releases/{releaseId}/artifacts and use the +/// returned signed upload URL to upload the artifact bytes +/// separately. /// {@endtemplate} -@JsonSerializable(includeIfNull: false) +@immutable class CreateReleaseArtifactRequest { /// {@macro create_release_artifact_request} const CreateReleaseArtifactRequest({ required this.arch, required this.platform, required this.hash, - required this.size, - required this.canSideload, required this.filename, - required this.podfileLockHash, + required this.size, + this.canSideload, + this.podfileLockHash, }); - /// Converts a `Map` to a [CreateReleaseArtifactRequest] - factory CreateReleaseArtifactRequest.fromJson(Map json) => - _$CreateReleaseArtifactRequestFromJson(json); + /// Converts a `Map` to a [CreateReleaseArtifactRequest]. + factory CreateReleaseArtifactRequest.fromJson(Map json) { + return parseFromJson( + 'CreateReleaseArtifactRequest', + json, + () => CreateReleaseArtifactRequest( + arch: json['arch'] as String, + platform: ReleasePlatform.fromJson(json['platform'] as String), + hash: json['hash'] as String, + filename: json['filename'] as String, + canSideload: json['can_sideload'] as bool?, + size: json['size'] as int, + podfileLockHash: json['podfile_lock_hash'] as String?, + ), + ); + } - /// Converts a [CreateReleaseArtifactRequest] to a `Map`. - Json toJson() => _$CreateReleaseArtifactRequestToJson(this); + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static CreateReleaseArtifactRequest? maybeFromJson( + Map? json, + ) { + if (json == null) { + return null; + } + return CreateReleaseArtifactRequest.fromJson(json); + } /// The arch of the artifact. final String arch; - /// The platform of the artifact. + /// A platform to which a Shorebird release can be deployed. final ReleasePlatform platform; /// The hash of the artifact. @@ -42,23 +62,49 @@ class CreateReleaseArtifactRequest { final String filename; /// Whether the artifact can installed and run on a device/emulator as-is. - @JsonKey(fromJson: _parseStringToBool, toJson: _parseBoolToString) final bool? canSideload; /// The size of the artifact in bytes. - @JsonKey(fromJson: _parseStringToInt, toJson: _parseIntToString) final int size; - /// The hash of the Podfile.lock file used to create this artifact (iOS only). + /// The hash of the Podfile.lock file used to create this artifact (iOS + /// only). final String? podfileLockHash; - static int _parseStringToInt(dynamic value) => int.parse(value as String); + /// Converts a [CreateReleaseArtifactRequest] to a `Map`. + Map toJson() { + return { + 'arch': arch, + 'platform': platform.toJson(), + 'hash': hash, + 'filename': filename, + 'can_sideload': canSideload, + 'size': size, + 'podfile_lock_hash': podfileLockHash, + }; + } - static String _parseIntToString(dynamic value) => value.toString(); + @override + int get hashCode => Object.hashAll([ + arch, + platform, + hash, + filename, + canSideload, + size, + podfileLockHash, + ]); - // Default to true - static bool _parseStringToBool(dynamic value) => - value == null || value == 'true'; - - static String _parseBoolToString(dynamic value) => value.toString(); + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is CreateReleaseArtifactRequest && + arch == other.arch && + platform == other.platform && + hash == other.hash && + filename == other.filename && + canSideload == other.canSideload && + size == other.size && + podfileLockHash == other.podfileLockHash; + } } diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/create_release_artifact/create_release_artifact_request.g.dart b/packages/shorebird_code_push_protocol/lib/src/messages/create_release_artifact/create_release_artifact_request.g.dart deleted file mode 100644 index ae6ec2e0..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/create_release_artifact/create_release_artifact_request.g.dart +++ /dev/null @@ -1,66 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ignore_for_file: implicit_dynamic_parameter, require_trailing_commas, cast_nullable_to_non_nullable, lines_longer_than_80_chars - -part of 'create_release_artifact_request.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -CreateReleaseArtifactRequest _$CreateReleaseArtifactRequestFromJson( - Map json, -) => $checkedCreate( - 'CreateReleaseArtifactRequest', - json, - ($checkedConvert) { - final val = CreateReleaseArtifactRequest( - arch: $checkedConvert('arch', (v) => v as String), - platform: $checkedConvert( - 'platform', - (v) => $enumDecode(_$ReleasePlatformEnumMap, v), - ), - hash: $checkedConvert('hash', (v) => v as String), - size: $checkedConvert( - 'size', - (v) => CreateReleaseArtifactRequest._parseStringToInt(v), - ), - canSideload: $checkedConvert( - 'can_sideload', - (v) => CreateReleaseArtifactRequest._parseStringToBool(v), - ), - filename: $checkedConvert('filename', (v) => v as String), - podfileLockHash: $checkedConvert( - 'podfile_lock_hash', - (v) => v as String?, - ), - ); - return val; - }, - fieldKeyMap: const { - 'canSideload': 'can_sideload', - 'podfileLockHash': 'podfile_lock_hash', - }, -); - -Map _$CreateReleaseArtifactRequestToJson( - CreateReleaseArtifactRequest instance, -) => { - 'arch': instance.arch, - 'platform': _$ReleasePlatformEnumMap[instance.platform]!, - 'hash': instance.hash, - 'filename': instance.filename, - 'can_sideload': CreateReleaseArtifactRequest._parseBoolToString( - instance.canSideload, - ), - 'size': CreateReleaseArtifactRequest._parseIntToString(instance.size), - 'podfile_lock_hash': ?instance.podfileLockHash, -}; - -const _$ReleasePlatformEnumMap = { - ReleasePlatform.android: 'android', - ReleasePlatform.ios: 'ios', - ReleasePlatform.linux: 'linux', - ReleasePlatform.macos: 'macos', - ReleasePlatform.windows: 'windows', -}; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/create_release_artifact/create_release_artifact_response.dart b/packages/shorebird_code_push_protocol/lib/src/messages/create_release_artifact/create_release_artifact_response.dart index 8dd9dfc0..bd37eee5 100644 --- a/packages/shorebird_code_push_protocol/lib/src/messages/create_release_artifact/create_release_artifact_response.dart +++ b/packages/shorebird_code_push_protocol/lib/src/messages/create_release_artifact/create_release_artifact_response.dart @@ -1,12 +1,11 @@ -import 'package:json_annotation/json_annotation.dart'; -import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; - -part 'create_release_artifact_response.g.dart'; +import 'package:meta/meta.dart'; +import 'package:shorebird_code_push_protocol/model_helpers.dart'; +import 'package:shorebird_code_push_protocol/src/models/release_platform.dart'; /// {@template create_release_artifact_response} -/// The response body for POST /api/v1/artifacts/:id/artifacts +/// The response body for registering a release artifact. /// {@endtemplate} -@JsonSerializable() +@immutable class CreateReleaseArtifactResponse { /// {@macro create_release_artifact_response} const CreateReleaseArtifactResponse({ @@ -19,14 +18,35 @@ class CreateReleaseArtifactResponse { required this.url, }); - /// Converts a `Map` to a [CreateReleaseArtifactResponse] - factory CreateReleaseArtifactResponse.fromJson(Map json) => - _$CreateReleaseArtifactResponseFromJson(json); + /// Converts a `Map` to a [CreateReleaseArtifactResponse]. + factory CreateReleaseArtifactResponse.fromJson(Map json) { + return parseFromJson( + 'CreateReleaseArtifactResponse', + json, + () => CreateReleaseArtifactResponse( + id: json['id'] as int, + releaseId: json['release_id'] as int, + arch: json['arch'] as String, + platform: ReleasePlatform.fromJson(json['platform'] as String), + hash: json['hash'] as String, + size: json['size'] as int, + url: json['url'] as String, + ), + ); + } - /// Converts a [CreateReleaseArtifactResponse] to a `Map`. - Json toJson() => _$CreateReleaseArtifactResponseToJson(this); + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static CreateReleaseArtifactResponse? maybeFromJson( + Map? json, + ) { + if (json == null) { + return null; + } + return CreateReleaseArtifactResponse.fromJson(json); + } - /// The ID of the artifact; + /// The ID of the artifact. final int id; /// The ID of the release. @@ -35,7 +55,7 @@ class CreateReleaseArtifactResponse { /// The arch of the artifact. final String arch; - /// The platform of the artifact. + /// A platform to which a Shorebird release can be deployed. final ReleasePlatform platform; /// The hash of the artifact. @@ -46,4 +66,41 @@ class CreateReleaseArtifactResponse { /// The upload URL for the artifact. final String url; + + /// Converts a [CreateReleaseArtifactResponse] to a `Map`. + Map toJson() { + return { + 'id': id, + 'release_id': releaseId, + 'arch': arch, + 'platform': platform.toJson(), + 'hash': hash, + 'size': size, + 'url': url, + }; + } + + @override + int get hashCode => Object.hashAll([ + id, + releaseId, + arch, + platform, + hash, + size, + url, + ]); + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is CreateReleaseArtifactResponse && + id == other.id && + releaseId == other.releaseId && + arch == other.arch && + platform == other.platform && + hash == other.hash && + size == other.size && + url == other.url; + } } diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/create_release_artifact/create_release_artifact_response.g.dart b/packages/shorebird_code_push_protocol/lib/src/messages/create_release_artifact/create_release_artifact_response.g.dart deleted file mode 100644 index 84f54f26..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/create_release_artifact/create_release_artifact_response.g.dart +++ /dev/null @@ -1,52 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ignore_for_file: implicit_dynamic_parameter, require_trailing_commas, cast_nullable_to_non_nullable, lines_longer_than_80_chars - -part of 'create_release_artifact_response.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -CreateReleaseArtifactResponse _$CreateReleaseArtifactResponseFromJson( - Map json, -) => $checkedCreate( - 'CreateReleaseArtifactResponse', - json, - ($checkedConvert) { - final val = CreateReleaseArtifactResponse( - id: $checkedConvert('id', (v) => (v as num).toInt()), - releaseId: $checkedConvert('release_id', (v) => (v as num).toInt()), - arch: $checkedConvert('arch', (v) => v as String), - platform: $checkedConvert( - 'platform', - (v) => $enumDecode(_$ReleasePlatformEnumMap, v), - ), - hash: $checkedConvert('hash', (v) => v as String), - size: $checkedConvert('size', (v) => (v as num).toInt()), - url: $checkedConvert('url', (v) => v as String), - ); - return val; - }, - fieldKeyMap: const {'releaseId': 'release_id'}, -); - -Map _$CreateReleaseArtifactResponseToJson( - CreateReleaseArtifactResponse instance, -) => { - 'id': instance.id, - 'release_id': instance.releaseId, - 'arch': instance.arch, - 'platform': _$ReleasePlatformEnumMap[instance.platform]!, - 'hash': instance.hash, - 'size': instance.size, - 'url': instance.url, -}; - -const _$ReleasePlatformEnumMap = { - ReleasePlatform.android: 'android', - ReleasePlatform.ios: 'ios', - ReleasePlatform.linux: 'linux', - ReleasePlatform.macos: 'macos', - ReleasePlatform.windows: 'windows', -}; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/create_user/create_user.dart b/packages/shorebird_code_push_protocol/lib/src/messages/create_user/create_user.dart deleted file mode 100644 index ab2dfd19..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/create_user/create_user.dart +++ /dev/null @@ -1 +0,0 @@ -export 'create_user_request.dart'; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/create_user/create_user_request.dart b/packages/shorebird_code_push_protocol/lib/src/messages/create_user/create_user_request.dart index 9e733266..7c2924c9 100644 --- a/packages/shorebird_code_push_protocol/lib/src/messages/create_user/create_user_request.dart +++ b/packages/shorebird_code_push_protocol/lib/src/messages/create_user/create_user_request.dart @@ -1,25 +1,53 @@ -import 'package:json_annotation/json_annotation.dart'; -import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; - -part 'create_user_request.g.dart'; +import 'package:meta/meta.dart'; +import 'package:shorebird_code_push_protocol/model_helpers.dart'; /// {@template create_user_request} -/// The request body for POST /api/v1/users, which creates a new User. -/// -/// Email is retrieved from the user's auth token. +/// The request body for POST /users. The user's email is taken +/// from the auth token; only the display name is provided here. /// {@endtemplate} -@JsonSerializable() +@immutable class CreateUserRequest { /// {@macro create_user_request} - const CreateUserRequest({required this.name}); + const CreateUserRequest({ + required this.name, + }); - /// Converts a JSON object to a [CreateUserRequest]. - factory CreateUserRequest.fromJson(Json json) => - _$CreateUserRequestFromJson(json); + /// Converts a `Map` to a [CreateUserRequest]. + factory CreateUserRequest.fromJson(Map json) { + return parseFromJson( + 'CreateUserRequest', + json, + () => CreateUserRequest( + name: json['name'] as String, + ), + ); + } - /// Converts a [CreateUserRequest] to a JSON object. - Json toJson() => _$CreateUserRequestToJson(this); + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static CreateUserRequest? maybeFromJson(Map? json) { + if (json == null) { + return null; + } + return CreateUserRequest.fromJson(json); + } /// The new user's display name. final String name; + + /// Converts a [CreateUserRequest] to a `Map`. + Map toJson() { + return { + 'name': name, + }; + } + + @override + int get hashCode => name.hashCode; + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is CreateUserRequest && name == other.name; + } } diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/create_user/create_user_request.g.dart b/packages/shorebird_code_push_protocol/lib/src/messages/create_user/create_user_request.g.dart deleted file mode 100644 index e8c9bc2f..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/create_user/create_user_request.g.dart +++ /dev/null @@ -1,20 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ignore_for_file: implicit_dynamic_parameter, require_trailing_commas, cast_nullable_to_non_nullable, lines_longer_than_80_chars - -part of 'create_user_request.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -CreateUserRequest _$CreateUserRequestFromJson(Map json) => - $checkedCreate('CreateUserRequest', json, ($checkedConvert) { - final val = CreateUserRequest( - name: $checkedConvert('name', (v) => v as String), - ); - return val; - }); - -Map _$CreateUserRequestToJson(CreateUserRequest instance) => - {'name': instance.name}; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/error_response.dart b/packages/shorebird_code_push_protocol/lib/src/messages/error_response.dart new file mode 100644 index 00000000..ffbb6c82 --- /dev/null +++ b/packages/shorebird_code_push_protocol/lib/src/messages/error_response.dart @@ -0,0 +1,71 @@ +import 'package:meta/meta.dart'; +import 'package:shorebird_code_push_protocol/model_helpers.dart'; + +/// {@template error_response} +/// Standard error response body from the Shorebird CodePush API. +/// {@endtemplate} +@immutable +class ErrorResponse { + /// {@macro error_response} + const ErrorResponse({ + required this.code, + required this.message, + this.details, + }); + + /// Converts a `Map` to an [ErrorResponse]. + factory ErrorResponse.fromJson(Map json) { + return parseFromJson( + 'ErrorResponse', + json, + () => ErrorResponse( + code: json['code'] as String, + message: json['message'] as String, + details: json['details'] as String?, + ), + ); + } + + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static ErrorResponse? maybeFromJson(Map? json) { + if (json == null) { + return null; + } + return ErrorResponse.fromJson(json); + } + + /// The unique error code. + final String code; + + /// Human-readable error message. + final String message; + + /// Optional details associated with the error. + final String? details; + + /// Converts an [ErrorResponse] to a `Map`. + Map toJson() { + return { + 'code': code, + 'message': message, + 'details': details, + }; + } + + @override + int get hashCode => Object.hashAll([ + code, + message, + details, + ]); + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is ErrorResponse && + code == other.code && + message == other.message && + details == other.details; + } +} diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/get_apps/get_apps.dart b/packages/shorebird_code_push_protocol/lib/src/messages/get_apps/get_apps.dart deleted file mode 100644 index ab943ad0..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/get_apps/get_apps.dart +++ /dev/null @@ -1 +0,0 @@ -export 'get_apps_response.dart'; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/get_apps/get_apps_response.dart b/packages/shorebird_code_push_protocol/lib/src/messages/get_apps/get_apps_response.dart index 84dd7a4a..13bf9fc3 100644 --- a/packages/shorebird_code_push_protocol/lib/src/messages/get_apps/get_apps_response.dart +++ b/packages/shorebird_code_push_protocol/lib/src/messages/get_apps/get_apps_response.dart @@ -1,23 +1,57 @@ -import 'package:json_annotation/json_annotation.dart'; -import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; - -part 'get_apps_response.g.dart'; +import 'package:meta/meta.dart'; +import 'package:shorebird_code_push_protocol/model_helpers.dart'; +import 'package:shorebird_code_push_protocol/src/models/app_metadata.dart'; /// {@template get_apps_response} -/// The response body for GET /api/v1/apps +/// The response body for GET /apps. /// {@endtemplate} -@JsonSerializable() +@immutable class GetAppsResponse { /// {@macro get_apps_response} - const GetAppsResponse({required this.apps}); + const GetAppsResponse({ + required this.apps, + }); /// Converts a `Map` to a [GetAppsResponse]. - factory GetAppsResponse.fromJson(Map json) => - _$GetAppsResponseFromJson(json); + factory GetAppsResponse.fromJson(Map json) { + return parseFromJson( + 'GetAppsResponse', + json, + () => GetAppsResponse( + apps: (json['apps'] as List) + .map( + (e) => AppMetadata.fromJson(e as Map), + ) + .toList(), + ), + ); + } - /// Converts a [GetAppsResponse] to a `Map`. - Json toJson() => _$GetAppsResponseToJson(this); + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static GetAppsResponse? maybeFromJson(Map? json) { + if (json == null) { + return null; + } + return GetAppsResponse.fromJson(json); + } /// The list of apps. final List apps; + + /// Converts a [GetAppsResponse] to a `Map`. + Map toJson() { + return { + 'apps': apps.map((e) => e.toJson()).toList(), + }; + } + + @override + int get hashCode => listHash(apps).hashCode; + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is GetAppsResponse && listsEqual(apps, other.apps); + } } diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/get_apps/get_apps_response.g.dart b/packages/shorebird_code_push_protocol/lib/src/messages/get_apps/get_apps_response.g.dart deleted file mode 100644 index 9056bfa6..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/get_apps/get_apps_response.g.dart +++ /dev/null @@ -1,25 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ignore_for_file: implicit_dynamic_parameter, require_trailing_commas, cast_nullable_to_non_nullable, lines_longer_than_80_chars - -part of 'get_apps_response.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -GetAppsResponse _$GetAppsResponseFromJson(Map json) => - $checkedCreate('GetAppsResponse', json, ($checkedConvert) { - final val = GetAppsResponse( - apps: $checkedConvert( - 'apps', - (v) => (v as List) - .map((e) => AppMetadata.fromJson(e as Map)) - .toList(), - ), - ); - return val; - }); - -Map _$GetAppsResponseToJson(GetAppsResponse instance) => - {'apps': instance.apps.map((e) => e.toJson()).toList()}; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/get_gcp_download_speed_test_url/get_gcp_download_speed_test_url200_response.dart b/packages/shorebird_code_push_protocol/lib/src/messages/get_gcp_download_speed_test_url/get_gcp_download_speed_test_url200_response.dart new file mode 100644 index 00000000..1185694f --- /dev/null +++ b/packages/shorebird_code_push_protocol/lib/src/messages/get_gcp_download_speed_test_url/get_gcp_download_speed_test_url200_response.dart @@ -0,0 +1,57 @@ +import 'package:meta/meta.dart'; +import 'package:shorebird_code_push_protocol/model_helpers.dart'; + +/// {@template get_gcp_download_speed_test_url200_response} +/// The download URL to measure against. +/// {@endtemplate} +@immutable +class GetGcpDownloadSpeedTestUrl200Response { + /// {@macro get_gcp_download_speed_test_url200_response} + const GetGcpDownloadSpeedTestUrl200Response({ + required this.downloadUrl, + }); + + /// Converts a `Map` to a [GetGcpDownloadSpeedTestUrl200Response]. + factory GetGcpDownloadSpeedTestUrl200Response.fromJson( + Map json, + ) { + return parseFromJson( + 'GetGcpDownloadSpeedTestUrl200Response', + json, + () => GetGcpDownloadSpeedTestUrl200Response( + downloadUrl: json['download_url'] as String, + ), + ); + } + + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static GetGcpDownloadSpeedTestUrl200Response? maybeFromJson( + Map? json, + ) { + if (json == null) { + return null; + } + return GetGcpDownloadSpeedTestUrl200Response.fromJson(json); + } + + /// The GCP-signed download URL. + final String downloadUrl; + + /// Converts a [GetGcpDownloadSpeedTestUrl200Response] to a `Map`. + Map toJson() { + return { + 'download_url': downloadUrl, + }; + } + + @override + int get hashCode => downloadUrl.hashCode; + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is GetGcpDownloadSpeedTestUrl200Response && + downloadUrl == other.downloadUrl; + } +} diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/get_gcp_upload_speed_test_url/get_gcp_upload_speed_test_url200_response.dart b/packages/shorebird_code_push_protocol/lib/src/messages/get_gcp_upload_speed_test_url/get_gcp_upload_speed_test_url200_response.dart new file mode 100644 index 00000000..ad74ff35 --- /dev/null +++ b/packages/shorebird_code_push_protocol/lib/src/messages/get_gcp_upload_speed_test_url/get_gcp_upload_speed_test_url200_response.dart @@ -0,0 +1,57 @@ +import 'package:meta/meta.dart'; +import 'package:shorebird_code_push_protocol/model_helpers.dart'; + +/// {@template get_gcp_upload_speed_test_url200_response} +/// The upload URL to measure against. +/// {@endtemplate} +@immutable +class GetGcpUploadSpeedTestUrl200Response { + /// {@macro get_gcp_upload_speed_test_url200_response} + const GetGcpUploadSpeedTestUrl200Response({ + required this.uploadUrl, + }); + + /// Converts a `Map` to a [GetGcpUploadSpeedTestUrl200Response]. + factory GetGcpUploadSpeedTestUrl200Response.fromJson( + Map json, + ) { + return parseFromJson( + 'GetGcpUploadSpeedTestUrl200Response', + json, + () => GetGcpUploadSpeedTestUrl200Response( + uploadUrl: json['upload_url'] as String, + ), + ); + } + + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static GetGcpUploadSpeedTestUrl200Response? maybeFromJson( + Map? json, + ) { + if (json == null) { + return null; + } + return GetGcpUploadSpeedTestUrl200Response.fromJson(json); + } + + /// The GCP-signed upload URL. + final String uploadUrl; + + /// Converts a [GetGcpUploadSpeedTestUrl200Response] to a `Map`. + Map toJson() { + return { + 'upload_url': uploadUrl, + }; + } + + @override + int get hashCode => uploadUrl.hashCode; + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is GetGcpUploadSpeedTestUrl200Response && + uploadUrl == other.uploadUrl; + } +} diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/get_organization_apps/get_organization_apps.dart b/packages/shorebird_code_push_protocol/lib/src/messages/get_organization_apps/get_organization_apps.dart deleted file mode 100644 index af882455..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/get_organization_apps/get_organization_apps.dart +++ /dev/null @@ -1 +0,0 @@ -export 'get_organization_apps_response.dart'; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/get_organization_apps/get_organization_apps_response.dart b/packages/shorebird_code_push_protocol/lib/src/messages/get_organization_apps/get_organization_apps_response.dart index a1a0e7f2..bad83115 100644 --- a/packages/shorebird_code_push_protocol/lib/src/messages/get_organization_apps/get_organization_apps_response.dart +++ b/packages/shorebird_code_push_protocol/lib/src/messages/get_organization_apps/get_organization_apps_response.dart @@ -1,25 +1,59 @@ -import 'package:json_annotation/json_annotation.dart'; -import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:meta/meta.dart'; +import 'package:shorebird_code_push_protocol/model_helpers.dart'; +import 'package:shorebird_code_push_protocol/src/models/app_metadata.dart'; -part 'get_organization_apps_response.g.dart'; - -/// {@template get_organization_apps_request} -/// A list of apps that belong to an organization. -/// -/// Body of GET /api/v1/organizations/:organizationId/apps +/// {@template get_organization_apps_response} +/// The response body for GET /organizations/{organizationId}/apps. /// {@endtemplate} -@JsonSerializable() +@immutable class GetOrganizationAppsResponse { - /// {@macro get_organization_apps_request} - GetOrganizationAppsResponse({required this.apps}); + /// {@macro get_organization_apps_response} + const GetOrganizationAppsResponse({ + required this.apps, + }); - /// Deserializes the [GetOrganizationAppsResponse] from a JSON map. - factory GetOrganizationAppsResponse.fromJson(Map json) => - _$GetOrganizationAppsResponseFromJson(json); + /// Converts a `Map` to a [GetOrganizationAppsResponse]. + factory GetOrganizationAppsResponse.fromJson(Map json) { + return parseFromJson( + 'GetOrganizationAppsResponse', + json, + () => GetOrganizationAppsResponse( + apps: (json['apps'] as List) + .map( + (e) => AppMetadata.fromJson(e as Map), + ) + .toList(), + ), + ); + } - /// Converts this [GetOrganizationAppsResponse] to a JSON map. - Map toJson() => _$GetOrganizationAppsResponseToJson(this); + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static GetOrganizationAppsResponse? maybeFromJson( + Map? json, + ) { + if (json == null) { + return null; + } + return GetOrganizationAppsResponse.fromJson(json); + } /// The apps that belong to the organization. final List apps; + + /// Converts a [GetOrganizationAppsResponse] to a `Map`. + Map toJson() { + return { + 'apps': apps.map((e) => e.toJson()).toList(), + }; + } + + @override + int get hashCode => listHash(apps).hashCode; + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is GetOrganizationAppsResponse && listsEqual(apps, other.apps); + } } diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/get_organization_apps/get_organization_apps_response.g.dart b/packages/shorebird_code_push_protocol/lib/src/messages/get_organization_apps/get_organization_apps_response.g.dart deleted file mode 100644 index 3944e1c1..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/get_organization_apps/get_organization_apps_response.g.dart +++ /dev/null @@ -1,27 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ignore_for_file: implicit_dynamic_parameter, require_trailing_commas, cast_nullable_to_non_nullable, lines_longer_than_80_chars - -part of 'get_organization_apps_response.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -GetOrganizationAppsResponse _$GetOrganizationAppsResponseFromJson( - Map json, -) => $checkedCreate('GetOrganizationAppsResponse', json, ($checkedConvert) { - final val = GetOrganizationAppsResponse( - apps: $checkedConvert( - 'apps', - (v) => (v as List) - .map((e) => AppMetadata.fromJson(e as Map)) - .toList(), - ), - ); - return val; -}); - -Map _$GetOrganizationAppsResponseToJson( - GetOrganizationAppsResponse instance, -) => {'apps': instance.apps.map((e) => e.toJson()).toList()}; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/get_organization_users/get_organization_users.dart b/packages/shorebird_code_push_protocol/lib/src/messages/get_organization_users/get_organization_users.dart deleted file mode 100644 index 9f6fd72f..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/get_organization_users/get_organization_users.dart +++ /dev/null @@ -1 +0,0 @@ -export 'get_organization_users_response.dart'; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/get_organization_users/get_organization_users_response.dart b/packages/shorebird_code_push_protocol/lib/src/messages/get_organization_users/get_organization_users_response.dart index 9356d3e6..28be9f05 100644 --- a/packages/shorebird_code_push_protocol/lib/src/messages/get_organization_users/get_organization_users_response.dart +++ b/packages/shorebird_code_push_protocol/lib/src/messages/get_organization_users/get_organization_users_response.dart @@ -1,27 +1,61 @@ -import 'package:json_annotation/json_annotation.dart'; -import 'package:shorebird_code_push_protocol/src/models/models.dart'; +import 'package:meta/meta.dart'; +import 'package:shorebird_code_push_protocol/model_helpers.dart'; +import 'package:shorebird_code_push_protocol/src/models/organization_user.dart'; -part 'get_organization_users_response.g.dart'; - -/// {@template get_organization_users_request} -/// A list of users that belong to an organization, as well as their roles in -/// the organization. -/// -/// The body of GET /api/v1/organizations/:organizationId/users +/// {@template get_organization_users_response} +/// The response body for GET /organizations/{organizationId}/users. /// {@endtemplate} -@JsonSerializable() +@immutable class GetOrganizationUsersResponse { - /// {@macro get_organization_users_request} - GetOrganizationUsersResponse({required this.users}); + /// {@macro get_organization_users_response} + const GetOrganizationUsersResponse({ + required this.users, + }); - /// Deserializes the [GetOrganizationUsersResponse] from a JSON map. - factory GetOrganizationUsersResponse.fromJson(Map json) => - _$GetOrganizationUsersResponseFromJson(json); + /// Converts a `Map` to a [GetOrganizationUsersResponse]. + factory GetOrganizationUsersResponse.fromJson(Map json) { + return parseFromJson( + 'GetOrganizationUsersResponse', + json, + () => GetOrganizationUsersResponse( + users: (json['users'] as List) + .map( + (e) => OrganizationUser.fromJson(e as Map), + ) + .toList(), + ), + ); + } - /// Converts this [GetOrganizationUsersResponse] to a JSON map. - Map toJson() => _$GetOrganizationUsersResponseToJson(this); + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static GetOrganizationUsersResponse? maybeFromJson( + Map? json, + ) { + if (json == null) { + return null; + } + return GetOrganizationUsersResponse.fromJson(json); + } - /// The list of users that belong to the organization, as well as their roles - /// in the organization. + /// The list of users that belong to the organization, as well as their + /// roles in the organization. final List users; + + /// Converts a [GetOrganizationUsersResponse] to a `Map`. + Map toJson() { + return { + 'users': users.map((e) => e.toJson()).toList(), + }; + } + + @override + int get hashCode => listHash(users).hashCode; + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is GetOrganizationUsersResponse && + listsEqual(users, other.users); + } } diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/get_organization_users/get_organization_users_response.g.dart b/packages/shorebird_code_push_protocol/lib/src/messages/get_organization_users/get_organization_users_response.g.dart deleted file mode 100644 index c40063fa..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/get_organization_users/get_organization_users_response.g.dart +++ /dev/null @@ -1,27 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ignore_for_file: implicit_dynamic_parameter, require_trailing_commas, cast_nullable_to_non_nullable, lines_longer_than_80_chars - -part of 'get_organization_users_response.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -GetOrganizationUsersResponse _$GetOrganizationUsersResponseFromJson( - Map json, -) => $checkedCreate('GetOrganizationUsersResponse', json, ($checkedConvert) { - final val = GetOrganizationUsersResponse( - users: $checkedConvert( - 'users', - (v) => (v as List) - .map((e) => OrganizationUser.fromJson(e as Map)) - .toList(), - ), - ); - return val; -}); - -Map _$GetOrganizationUsersResponseToJson( - GetOrganizationUsersResponse instance, -) => {'users': instance.users.map((e) => e.toJson()).toList()}; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/get_organizations/get_organizations.dart b/packages/shorebird_code_push_protocol/lib/src/messages/get_organizations/get_organizations.dart deleted file mode 100644 index 10168e5d..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/get_organizations/get_organizations.dart +++ /dev/null @@ -1 +0,0 @@ -export 'get_organizations_response.dart'; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/get_organizations/get_organizations_response.dart b/packages/shorebird_code_push_protocol/lib/src/messages/get_organizations/get_organizations_response.dart deleted file mode 100644 index dad074bb..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/get_organizations/get_organizations_response.dart +++ /dev/null @@ -1,26 +0,0 @@ -import 'package:json_annotation/json_annotation.dart'; -import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; - -part 'get_organizations_response.g.dart'; - -/// {@template get_organizations_request} -/// A list of organizations the currently logged in user is a member of. -/// -/// Body of /api/v1/organizations. -/// {@endtemplate} -@JsonSerializable() -class GetOrganizationsResponse { - /// {@macro get_organizations_request} - GetOrganizationsResponse({required this.organizations}); - - /// Deserializes the [GetOrganizationsResponse] from a JSON map. - factory GetOrganizationsResponse.fromJson(Map json) => - _$GetOrganizationsResponseFromJson(json); - - /// Converts this [GetOrganizationsResponse] to a JSON map. - Map toJson() => _$GetOrganizationsResponseToJson(this); - - /// Organizations that the user is a member of, as well as this user's role in - /// each organization. - final List organizations; -} diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/get_organizations/get_organizations_response.g.dart b/packages/shorebird_code_push_protocol/lib/src/messages/get_organizations/get_organizations_response.g.dart deleted file mode 100644 index fc27cfab..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/get_organizations/get_organizations_response.g.dart +++ /dev/null @@ -1,31 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ignore_for_file: implicit_dynamic_parameter, require_trailing_commas, cast_nullable_to_non_nullable, lines_longer_than_80_chars - -part of 'get_organizations_response.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -GetOrganizationsResponse _$GetOrganizationsResponseFromJson( - Map json, -) => $checkedCreate('GetOrganizationsResponse', json, ($checkedConvert) { - final val = GetOrganizationsResponse( - organizations: $checkedConvert( - 'organizations', - (v) => (v as List) - .map( - (e) => OrganizationMembership.fromJson(e as Map), - ) - .toList(), - ), - ); - return val; -}); - -Map _$GetOrganizationsResponseToJson( - GetOrganizationsResponse instance, -) => { - 'organizations': instance.organizations.map((e) => e.toJson()).toList(), -}; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/get_organizations_response.dart b/packages/shorebird_code_push_protocol/lib/src/messages/get_organizations_response.dart new file mode 100644 index 00000000..77d7fb07 --- /dev/null +++ b/packages/shorebird_code_push_protocol/lib/src/messages/get_organizations_response.dart @@ -0,0 +1,59 @@ +import 'package:meta/meta.dart'; +import 'package:shorebird_code_push_protocol/model_helpers.dart'; +import 'package:shorebird_code_push_protocol/src/models/organization_membership.dart'; + +/// {@template get_organizations_response} +/// The response body for GET /organizations. +/// {@endtemplate} +@immutable +class GetOrganizationsResponse { + /// {@macro get_organizations_response} + const GetOrganizationsResponse({ + required this.organizations, + }); + + /// Converts a `Map` to a [GetOrganizationsResponse]. + factory GetOrganizationsResponse.fromJson(Map json) { + return parseFromJson( + 'GetOrganizationsResponse', + json, + () => GetOrganizationsResponse( + organizations: (json['organizations'] as List) + .map( + (e) => OrganizationMembership.fromJson(e as Map), + ) + .toList(), + ), + ); + } + + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static GetOrganizationsResponse? maybeFromJson(Map? json) { + if (json == null) { + return null; + } + return GetOrganizationsResponse.fromJson(json); + } + + /// Organizations that the user is a member of, as well as this user's role + /// in each organization. + final List organizations; + + /// Converts a [GetOrganizationsResponse] to a `Map`. + Map toJson() { + return { + 'organizations': organizations.map((e) => e.toJson()).toList(), + }; + } + + @override + int get hashCode => listHash(organizations).hashCode; + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is GetOrganizationsResponse && + listsEqual(organizations, other.organizations); + } +} diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/get_release/get_release.dart b/packages/shorebird_code_push_protocol/lib/src/messages/get_release/get_release.dart deleted file mode 100644 index 586ed1f2..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/get_release/get_release.dart +++ /dev/null @@ -1 +0,0 @@ -export 'get_release_response.dart'; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/get_release/get_release_response.dart b/packages/shorebird_code_push_protocol/lib/src/messages/get_release/get_release_response.dart index eb8e1440..9e9c0c95 100644 --- a/packages/shorebird_code_push_protocol/lib/src/messages/get_release/get_release_response.dart +++ b/packages/shorebird_code_push_protocol/lib/src/messages/get_release/get_release_response.dart @@ -1,23 +1,54 @@ -import 'package:json_annotation/json_annotation.dart'; -import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; - -part 'get_release_response.g.dart'; +import 'package:meta/meta.dart'; +import 'package:shorebird_code_push_protocol/model_helpers.dart'; +import 'package:shorebird_code_push_protocol/src/models/release.dart'; /// {@template get_release_response} -/// The response body for GET /api/v1/apps/:id/releases/:releaseId +/// The response body for GET /apps/{appId}/releases/{releaseId}. /// {@endtemplate} -@JsonSerializable() +@immutable class GetReleaseResponse { /// {@macro get_release_response} - const GetReleaseResponse({required this.release}); + const GetReleaseResponse({ + required this.release, + }); /// Converts a `Map` to a [GetReleaseResponse]. - factory GetReleaseResponse.fromJson(Map json) => - _$GetReleaseResponseFromJson(json); + factory GetReleaseResponse.fromJson(Map json) { + return parseFromJson( + 'GetReleaseResponse', + json, + () => GetReleaseResponse( + release: Release.fromJson(json['release'] as Map), + ), + ); + } + + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static GetReleaseResponse? maybeFromJson(Map? json) { + if (json == null) { + return null; + } + return GetReleaseResponse.fromJson(json); + } + + /// A release build of an application that is distributed to devices. + /// A release can have zero or more patches applied to it. + final Release release; /// Converts a [GetReleaseResponse] to a `Map`. - Map toJson() => _$GetReleaseResponseToJson(this); + Map toJson() { + return { + 'release': release.toJson(), + }; + } - /// The requested release. - final Release release; + @override + int get hashCode => release.hashCode; + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is GetReleaseResponse && release == other.release; + } } diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/get_release/get_release_response.g.dart b/packages/shorebird_code_push_protocol/lib/src/messages/get_release/get_release_response.g.dart deleted file mode 100644 index 30108b6e..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/get_release/get_release_response.g.dart +++ /dev/null @@ -1,23 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ignore_for_file: implicit_dynamic_parameter, require_trailing_commas, cast_nullable_to_non_nullable, lines_longer_than_80_chars - -part of 'get_release_response.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -GetReleaseResponse _$GetReleaseResponseFromJson(Map json) => - $checkedCreate('GetReleaseResponse', json, ($checkedConvert) { - final val = GetReleaseResponse( - release: $checkedConvert( - 'release', - (v) => Release.fromJson(v as Map), - ), - ); - return val; - }); - -Map _$GetReleaseResponseToJson(GetReleaseResponse instance) => - {'release': instance.release.toJson()}; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/get_release_artifacts/get_release_artifacts.dart b/packages/shorebird_code_push_protocol/lib/src/messages/get_release_artifacts/get_release_artifacts.dart deleted file mode 100644 index 7fa21f66..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/get_release_artifacts/get_release_artifacts.dart +++ /dev/null @@ -1 +0,0 @@ -export 'get_release_artifacts_response.dart'; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/get_release_artifacts/get_release_artifacts_response.dart b/packages/shorebird_code_push_protocol/lib/src/messages/get_release_artifacts/get_release_artifacts_response.dart index 0718e8d9..b1328505 100644 --- a/packages/shorebird_code_push_protocol/lib/src/messages/get_release_artifacts/get_release_artifacts_response.dart +++ b/packages/shorebird_code_push_protocol/lib/src/messages/get_release_artifacts/get_release_artifacts_response.dart @@ -1,23 +1,60 @@ -import 'package:json_annotation/json_annotation.dart'; -import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; - -part 'get_release_artifacts_response.g.dart'; +import 'package:meta/meta.dart'; +import 'package:shorebird_code_push_protocol/model_helpers.dart'; +import 'package:shorebird_code_push_protocol/src/models/release_artifact.dart'; /// {@template get_release_artifacts_response} -/// The response body for GET /api/v1/release/:release/artifacts +/// The response body for GET /apps/{appId}/releases/{releaseId}/artifacts. /// {@endtemplate} -@JsonSerializable() +@immutable class GetReleaseArtifactsResponse { /// {@macro get_release_artifacts_response} - const GetReleaseArtifactsResponse({required this.artifacts}); + const GetReleaseArtifactsResponse({ + required this.artifacts, + }); /// Converts a `Map` to a [GetReleaseArtifactsResponse]. - factory GetReleaseArtifactsResponse.fromJson(Map json) => - _$GetReleaseArtifactsResponseFromJson(json); + factory GetReleaseArtifactsResponse.fromJson(Map json) { + return parseFromJson( + 'GetReleaseArtifactsResponse', + json, + () => GetReleaseArtifactsResponse( + artifacts: (json['artifacts'] as List) + .map( + (e) => ReleaseArtifact.fromJson(e as Map), + ) + .toList(), + ), + ); + } - /// Converts a [GetReleaseArtifactsResponse] to a `Map`. - Json toJson() => _$GetReleaseArtifactsResponseToJson(this); + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static GetReleaseArtifactsResponse? maybeFromJson( + Map? json, + ) { + if (json == null) { + return null; + } + return GetReleaseArtifactsResponse.fromJson(json); + } /// The artifacts for the release. final List artifacts; + + /// Converts a [GetReleaseArtifactsResponse] to a `Map`. + Map toJson() { + return { + 'artifacts': artifacts.map((e) => e.toJson()).toList(), + }; + } + + @override + int get hashCode => listHash(artifacts).hashCode; + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is GetReleaseArtifactsResponse && + listsEqual(artifacts, other.artifacts); + } } diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/get_release_artifacts/get_release_artifacts_response.g.dart b/packages/shorebird_code_push_protocol/lib/src/messages/get_release_artifacts/get_release_artifacts_response.g.dart deleted file mode 100644 index f6ce94fb..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/get_release_artifacts/get_release_artifacts_response.g.dart +++ /dev/null @@ -1,29 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ignore_for_file: implicit_dynamic_parameter, require_trailing_commas, cast_nullable_to_non_nullable, lines_longer_than_80_chars - -part of 'get_release_artifacts_response.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -GetReleaseArtifactsResponse _$GetReleaseArtifactsResponseFromJson( - Map json, -) => $checkedCreate('GetReleaseArtifactsResponse', json, ($checkedConvert) { - final val = GetReleaseArtifactsResponse( - artifacts: $checkedConvert( - 'artifacts', - (v) => (v as List) - .map((e) => ReleaseArtifact.fromJson(e as Map)) - .toList(), - ), - ); - return val; -}); - -Map _$GetReleaseArtifactsResponseToJson( - GetReleaseArtifactsResponse instance, -) => { - 'artifacts': instance.artifacts.map((e) => e.toJson()).toList(), -}; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/get_release_patches/get_release_patches.dart b/packages/shorebird_code_push_protocol/lib/src/messages/get_release_patches/get_release_patches.dart deleted file mode 100644 index 77d0e8f8..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/get_release_patches/get_release_patches.dart +++ /dev/null @@ -1 +0,0 @@ -export 'get_release_patches_response.dart'; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/get_release_patches/get_release_patches_response.dart b/packages/shorebird_code_push_protocol/lib/src/messages/get_release_patches/get_release_patches_response.dart index 267dfc79..d6e33700 100644 --- a/packages/shorebird_code_push_protocol/lib/src/messages/get_release_patches/get_release_patches_response.dart +++ b/packages/shorebird_code_push_protocol/lib/src/messages/get_release_patches/get_release_patches_response.dart @@ -1,23 +1,58 @@ -import 'package:json_annotation/json_annotation.dart'; -import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; - -part 'get_release_patches_response.g.dart'; +import 'package:meta/meta.dart'; +import 'package:shorebird_code_push_protocol/model_helpers.dart'; +import 'package:shorebird_code_push_protocol/src/models/release_patch.dart'; /// {@template get_release_patches_response} -/// The response to /api/v1/apps/$appId/releases/$releaseId/patches +/// The response to GET /apps/{appId}/releases/{releaseId}/patches. /// {@endtemplate} -@JsonSerializable() +@immutable class GetReleasePatchesResponse { /// {@macro get_release_patches_response} - const GetReleasePatchesResponse({required this.patches}); + const GetReleasePatchesResponse({ + required this.patches, + }); - /// Converts a `Map` to a [GetReleasePatchesResponse] - factory GetReleasePatchesResponse.fromJson(Map json) => - _$GetReleasePatchesResponseFromJson(json); + /// Converts a `Map` to a [GetReleasePatchesResponse]. + factory GetReleasePatchesResponse.fromJson(Map json) { + return parseFromJson( + 'GetReleasePatchesResponse', + json, + () => GetReleasePatchesResponse( + patches: (json['patches'] as List) + .map( + (e) => ReleasePatch.fromJson(e as Map), + ) + .toList(), + ), + ); + } - /// Converts a [GetReleasePatchesResponse] to a `Map` - Json toJson() => _$GetReleasePatchesResponseToJson(this); + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static GetReleasePatchesResponse? maybeFromJson(Map? json) { + if (json == null) { + return null; + } + return GetReleasePatchesResponse.fromJson(json); + } /// List of patches. final List patches; + + /// Converts a [GetReleasePatchesResponse] to a `Map`. + Map toJson() { + return { + 'patches': patches.map((e) => e.toJson()).toList(), + }; + } + + @override + int get hashCode => listHash(patches).hashCode; + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is GetReleasePatchesResponse && + listsEqual(patches, other.patches); + } } diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/get_release_patches/get_release_patches_response.g.dart b/packages/shorebird_code_push_protocol/lib/src/messages/get_release_patches/get_release_patches_response.g.dart deleted file mode 100644 index 020347b7..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/get_release_patches/get_release_patches_response.g.dart +++ /dev/null @@ -1,29 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ignore_for_file: implicit_dynamic_parameter, require_trailing_commas, cast_nullable_to_non_nullable, lines_longer_than_80_chars - -part of 'get_release_patches_response.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -GetReleasePatchesResponse _$GetReleasePatchesResponseFromJson( - Map json, -) => $checkedCreate('GetReleasePatchesResponse', json, ($checkedConvert) { - final val = GetReleasePatchesResponse( - patches: $checkedConvert( - 'patches', - (v) => (v as List) - .map((e) => ReleasePatch.fromJson(e as Map)) - .toList(), - ), - ); - return val; -}); - -Map _$GetReleasePatchesResponseToJson( - GetReleasePatchesResponse instance, -) => { - 'patches': instance.patches.map((e) => e.toJson()).toList(), -}; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/get_releases/get_releases.dart b/packages/shorebird_code_push_protocol/lib/src/messages/get_releases/get_releases.dart deleted file mode 100644 index f954ff8a..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/get_releases/get_releases.dart +++ /dev/null @@ -1 +0,0 @@ -export 'get_releases_response.dart'; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/get_releases/get_releases_response.dart b/packages/shorebird_code_push_protocol/lib/src/messages/get_releases/get_releases_response.dart index 12366b77..23fcd481 100644 --- a/packages/shorebird_code_push_protocol/lib/src/messages/get_releases/get_releases_response.dart +++ b/packages/shorebird_code_push_protocol/lib/src/messages/get_releases/get_releases_response.dart @@ -1,23 +1,55 @@ -import 'package:json_annotation/json_annotation.dart'; -import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; - -part 'get_releases_response.g.dart'; +import 'package:meta/meta.dart'; +import 'package:shorebird_code_push_protocol/model_helpers.dart'; +import 'package:shorebird_code_push_protocol/src/models/release.dart'; /// {@template get_releases_response} -/// The response body for GET /api/v1/apps/:id/releases +/// The response body for GET /apps/{appId}/releases. /// {@endtemplate} -@JsonSerializable() +@immutable class GetReleasesResponse { /// {@macro get_releases_response} - const GetReleasesResponse({required this.releases}); + const GetReleasesResponse({ + required this.releases, + }); /// Converts a `Map` to a [GetReleasesResponse]. - factory GetReleasesResponse.fromJson(Map json) => - _$GetReleasesResponseFromJson(json); + factory GetReleasesResponse.fromJson(Map json) { + return parseFromJson( + 'GetReleasesResponse', + json, + () => GetReleasesResponse( + releases: (json['releases'] as List) + .map((e) => Release.fromJson(e as Map)) + .toList(), + ), + ); + } - /// Converts a [GetReleasesResponse] to a `Map`. - Json toJson() => _$GetReleasesResponseToJson(this); + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static GetReleasesResponse? maybeFromJson(Map? json) { + if (json == null) { + return null; + } + return GetReleasesResponse.fromJson(json); + } /// The list of releases for the app. final List releases; + + /// Converts a [GetReleasesResponse] to a `Map`. + Map toJson() { + return { + 'releases': releases.map((e) => e.toJson()).toList(), + }; + } + + @override + int get hashCode => listHash(releases).hashCode; + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is GetReleasesResponse && listsEqual(releases, other.releases); + } } diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/get_releases/get_releases_response.g.dart b/packages/shorebird_code_push_protocol/lib/src/messages/get_releases/get_releases_response.g.dart deleted file mode 100644 index d3d36844..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/get_releases/get_releases_response.g.dart +++ /dev/null @@ -1,28 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ignore_for_file: implicit_dynamic_parameter, require_trailing_commas, cast_nullable_to_non_nullable, lines_longer_than_80_chars - -part of 'get_releases_response.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -GetReleasesResponse _$GetReleasesResponseFromJson(Map json) => - $checkedCreate('GetReleasesResponse', json, ($checkedConvert) { - final val = GetReleasesResponse( - releases: $checkedConvert( - 'releases', - (v) => (v as List) - .map((e) => Release.fromJson(e as Map)) - .toList(), - ), - ); - return val; - }); - -Map _$GetReleasesResponseToJson( - GetReleasesResponse instance, -) => { - 'releases': instance.releases.map((e) => e.toJson()).toList(), -}; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/messages.dart b/packages/shorebird_code_push_protocol/lib/src/messages/messages.dart deleted file mode 100644 index 828a8661..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/messages.dart +++ /dev/null @@ -1,21 +0,0 @@ -export 'create_app/create_app.dart'; -export 'create_app_collaborator/create_app_collaborator.dart'; -export 'create_channel/create_channel.dart'; -export 'create_patch/create_patch.dart'; -export 'create_patch_artifact/create_patch_artifact.dart'; -export 'create_release/create_release.dart'; -export 'create_release_artifact/create_release_artifact.dart'; -export 'create_user/create_user.dart'; -export 'get_apps/get_apps.dart'; -export 'get_organization_apps/get_organization_apps.dart'; -export 'get_organization_users/get_organization_users.dart'; -export 'get_organizations/get_organizations.dart'; -export 'get_release/get_release.dart'; -export 'get_release_artifacts/get_release_artifacts.dart'; -export 'get_release_patches/get_release_patches.dart'; -export 'get_releases/get_releases.dart'; -export 'patch_check/patch_check.dart'; -export 'promote_patch/promote_patch.dart'; -export 'update_app_collaborator/update_app_collaborator.dart'; -export 'update_patch/update_patch.dart'; -export 'update_release/update_release.dart'; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/patch_check/patch_check.dart b/packages/shorebird_code_push_protocol/lib/src/messages/patch_check/patch_check.dart deleted file mode 100644 index 3bb2106f..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/patch_check/patch_check.dart +++ /dev/null @@ -1,2 +0,0 @@ -export 'patch_check_request.dart'; -export 'patch_check_response.dart'; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/patch_check/patch_check_request.dart b/packages/shorebird_code_push_protocol/lib/src/messages/patch_check/patch_check_request.dart index ec064cc6..88688cd1 100644 --- a/packages/shorebird_code_push_protocol/lib/src/messages/patch_check/patch_check_request.dart +++ b/packages/shorebird_code_push_protocol/lib/src/messages/patch_check/patch_check_request.dart @@ -1,46 +1,63 @@ -import 'package:equatable/equatable.dart'; -import 'package:json_annotation/json_annotation.dart'; -import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; - -part 'patch_check_request.g.dart'; +import 'package:meta/meta.dart'; +import 'package:shorebird_code_push_protocol/model_helpers.dart'; +import 'package:shorebird_code_push_protocol/src/models/release_platform.dart'; /// {@template patch_check_request} -/// The request body for POST /api/v1/patches/check +/// The request body for POST /patches/check. /// {@endtemplate} -@JsonSerializable() -class PatchCheckRequest extends Equatable { +@immutable +class PatchCheckRequest { /// {@macro patch_check_request} const PatchCheckRequest({ required this.releaseVersion, - required this.patchNumber, - required this.patchHash, required this.platform, required this.arch, required this.appId, required this.channel, + this.patchNumber, + this.patchHash, this.clientId, }); - /// Converts a `Map` to a [PatchCheckRequest] - factory PatchCheckRequest.fromJson(Map json) => - _$PatchCheckRequestFromJson(json); + /// Converts a `Map` to a [PatchCheckRequest]. + factory PatchCheckRequest.fromJson(Map json) { + return parseFromJson( + 'PatchCheckRequest', + json, + () => PatchCheckRequest( + releaseVersion: json['release_version'] as String, + patchNumber: json['patch_number'] as int?, + patchHash: json['patch_hash'] as String?, + platform: ReleasePlatform.fromJson(json['platform'] as String), + arch: json['arch'] as String, + appId: json['app_id'] as String, + channel: json['channel'] as String, + clientId: json['client_id'] as String?, + ), + ); + } - /// Converts a [PatchCheckRequest] to a `Map` - Map toJson() => _$PatchCheckRequestToJson(this); + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static PatchCheckRequest? maybeFromJson(Map? json) { + if (json == null) { + return null; + } + return PatchCheckRequest.fromJson(json); + } /// The release version of the app. final String releaseVersion; - /// The highest patch number that the client has downloaded. - /// If provided, the server will only return patches with a higher patch - /// number. - /// If not provided, the server will provide the latest available patch. + /// The highest patch number the client has already downloaded. + /// If provided, the server only returns patches with a higher + /// number. If omitted, the server returns the latest available. final int? patchNumber; /// The current patch hash of the app. final String? patchHash; - /// The platform of the app. + /// A platform to which a Shorebird release can be deployed. final ReleasePlatform platform; /// The architecture of the app. @@ -52,15 +69,26 @@ class PatchCheckRequest extends Equatable { /// The channel of the app. final String channel; - /// The unique ID of the device being updated. This ID is generated on the - /// device and is unique per app. - /// - /// This is nullable because we only started reporting this value in November - /// 2025. We should eventually make it non-nullable. + /// Unique device ID for the install, generated on device and + /// unique per app. Optional for backward compatibility. final String? clientId; + /// Converts a [PatchCheckRequest] to a `Map`. + Map toJson() { + return { + 'release_version': releaseVersion, + 'patch_number': patchNumber, + 'patch_hash': patchHash, + 'platform': platform.toJson(), + 'arch': arch, + 'app_id': appId, + 'channel': channel, + 'client_id': clientId, + }; + } + @override - List get props => [ + int get hashCode => Object.hashAll([ releaseVersion, patchNumber, patchHash, @@ -69,5 +97,19 @@ class PatchCheckRequest extends Equatable { appId, channel, clientId, - ]; + ]); + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is PatchCheckRequest && + releaseVersion == other.releaseVersion && + patchNumber == other.patchNumber && + patchHash == other.patchHash && + platform == other.platform && + arch == other.arch && + appId == other.appId && + channel == other.channel && + clientId == other.clientId; + } } diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/patch_check/patch_check_request.g.dart b/packages/shorebird_code_push_protocol/lib/src/messages/patch_check/patch_check_request.g.dart deleted file mode 100644 index 3dfb851f..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/patch_check/patch_check_request.g.dart +++ /dev/null @@ -1,59 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ignore_for_file: implicit_dynamic_parameter, require_trailing_commas, cast_nullable_to_non_nullable, lines_longer_than_80_chars - -part of 'patch_check_request.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -PatchCheckRequest _$PatchCheckRequestFromJson( - Map json, -) => $checkedCreate( - 'PatchCheckRequest', - json, - ($checkedConvert) { - final val = PatchCheckRequest( - releaseVersion: $checkedConvert('release_version', (v) => v as String), - patchNumber: $checkedConvert('patch_number', (v) => (v as num?)?.toInt()), - patchHash: $checkedConvert('patch_hash', (v) => v as String?), - platform: $checkedConvert( - 'platform', - (v) => $enumDecode(_$ReleasePlatformEnumMap, v), - ), - arch: $checkedConvert('arch', (v) => v as String), - appId: $checkedConvert('app_id', (v) => v as String), - channel: $checkedConvert('channel', (v) => v as String), - clientId: $checkedConvert('client_id', (v) => v as String?), - ); - return val; - }, - fieldKeyMap: const { - 'releaseVersion': 'release_version', - 'patchNumber': 'patch_number', - 'patchHash': 'patch_hash', - 'appId': 'app_id', - 'clientId': 'client_id', - }, -); - -Map _$PatchCheckRequestToJson(PatchCheckRequest instance) => - { - 'release_version': instance.releaseVersion, - 'patch_number': instance.patchNumber, - 'patch_hash': instance.patchHash, - 'platform': _$ReleasePlatformEnumMap[instance.platform]!, - 'arch': instance.arch, - 'app_id': instance.appId, - 'channel': instance.channel, - 'client_id': instance.clientId, - }; - -const _$ReleasePlatformEnumMap = { - ReleasePlatform.android: 'android', - ReleasePlatform.ios: 'ios', - ReleasePlatform.linux: 'linux', - ReleasePlatform.macos: 'macos', - ReleasePlatform.windows: 'windows', -}; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/patch_check/patch_check_response.dart b/packages/shorebird_code_push_protocol/lib/src/messages/patch_check/patch_check_response.dart index c4dffd67..841b60c0 100644 --- a/packages/shorebird_code_push_protocol/lib/src/messages/patch_check/patch_check_response.dart +++ b/packages/shorebird_code_push_protocol/lib/src/messages/patch_check/patch_check_response.dart @@ -1,13 +1,12 @@ -import 'package:equatable/equatable.dart'; -import 'package:json_annotation/json_annotation.dart'; - -part 'patch_check_response.g.dart'; +import 'package:meta/meta.dart'; +import 'package:shorebird_code_push_protocol/model_helpers.dart'; +import 'package:shorebird_code_push_protocol/src/models/patch_check_metadata.dart'; /// {@template patch_check_response} -/// The response body for POST /api/v1/patches/check +/// The response body for POST /patches/check. /// {@endtemplate} -@JsonSerializable() -class PatchCheckResponse extends Equatable { +@immutable +class PatchCheckResponse { /// {@macro patch_check_response} const PatchCheckResponse({ required this.patchAvailable, @@ -15,61 +14,64 @@ class PatchCheckResponse extends Equatable { this.rolledBackPatchNumbers, }); - /// Converts a `Map` to a [PatchCheckResponse] - factory PatchCheckResponse.fromJson(Map json) => - _$PatchCheckResponseFromJson(json); + /// Converts a `Map` to a [PatchCheckResponse]. + factory PatchCheckResponse.fromJson(Map json) { + return parseFromJson( + 'PatchCheckResponse', + json, + () => PatchCheckResponse( + patchAvailable: json['patch_available'] as bool, + patch: PatchCheckMetadata.maybeFromJson( + json['patch'] as Map?, + ), + rolledBackPatchNumbers: (json['rolled_back_patch_numbers'] as List?) + ?.cast(), + ), + ); + } - /// Converts a [PatchCheckResponse] to a `Map` - Map toJson() => _$PatchCheckResponseToJson(this); + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static PatchCheckResponse? maybeFromJson(Map? json) { + if (json == null) { + return null; + } + return PatchCheckResponse.fromJson(json); + } /// Whether a patch is available. final bool patchAvailable; - /// The patch metadata. + /// Patch metadata representing the contents of a patch for a + /// specific platform and architecture. final PatchCheckMetadata? patch; /// The numbers of all patches that have been rolled back for the current /// release. final List? rolledBackPatchNumbers; - @override - List get props => [patchAvailable, patch, rolledBackPatchNumbers]; -} - -/// {@template patch_check_metadata} -/// Patch metadata represents the contents of an update (patch) for a specific -/// platform and architecture. -/// {@endtemplate} -@JsonSerializable() -class PatchCheckMetadata extends Equatable { - /// {@macro patch_check_metadata} - const PatchCheckMetadata({ - required this.number, - required this.downloadUrl, - required this.hash, - required this.hashSignature, - }); - - /// Converts a `Map` to an [PatchCheckMetadata] - factory PatchCheckMetadata.fromJson(Map json) => - _$PatchCheckMetadataFromJson(json); - - /// Converts an [PatchCheckMetadata] to a `Map` - Map toJson() => _$PatchCheckMetadataToJson(this); - - /// The patch number associated with the artifact. - final int number; - - /// The URL of the artifact. - final String downloadUrl; - - /// The hash of the artifact. - final String hash; - - /// The signature of the [hash]. - @JsonKey(includeIfNull: false) - final String? hashSignature; + /// Converts a [PatchCheckResponse] to a `Map`. + Map toJson() { + return { + 'patch_available': patchAvailable, + 'patch': patch?.toJson(), + 'rolled_back_patch_numbers': rolledBackPatchNumbers, + }; + } @override - List get props => [number, downloadUrl, hash, hashSignature]; + int get hashCode => Object.hashAll([ + patchAvailable, + patch, + listHash(rolledBackPatchNumbers), + ]); + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is PatchCheckResponse && + patchAvailable == other.patchAvailable && + patch == other.patch && + listsEqual(rolledBackPatchNumbers, other.rolledBackPatchNumbers); + } } diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/patch_check/patch_check_response.g.dart b/packages/shorebird_code_push_protocol/lib/src/messages/patch_check/patch_check_response.g.dart deleted file mode 100644 index 4a7e3543..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/patch_check/patch_check_response.g.dart +++ /dev/null @@ -1,70 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ignore_for_file: implicit_dynamic_parameter, require_trailing_commas, cast_nullable_to_non_nullable, lines_longer_than_80_chars - -part of 'patch_check_response.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -PatchCheckResponse _$PatchCheckResponseFromJson(Map json) => - $checkedCreate( - 'PatchCheckResponse', - json, - ($checkedConvert) { - final val = PatchCheckResponse( - patchAvailable: $checkedConvert('patch_available', (v) => v as bool), - patch: $checkedConvert( - 'patch', - (v) => v == null - ? null - : PatchCheckMetadata.fromJson(v as Map), - ), - rolledBackPatchNumbers: $checkedConvert( - 'rolled_back_patch_numbers', - (v) => - (v as List?)?.map((e) => (e as num).toInt()).toList(), - ), - ); - return val; - }, - fieldKeyMap: const { - 'patchAvailable': 'patch_available', - 'rolledBackPatchNumbers': 'rolled_back_patch_numbers', - }, - ); - -Map _$PatchCheckResponseToJson(PatchCheckResponse instance) => - { - 'patch_available': instance.patchAvailable, - 'patch': instance.patch?.toJson(), - 'rolled_back_patch_numbers': instance.rolledBackPatchNumbers, - }; - -PatchCheckMetadata _$PatchCheckMetadataFromJson(Map json) => - $checkedCreate( - 'PatchCheckMetadata', - json, - ($checkedConvert) { - final val = PatchCheckMetadata( - number: $checkedConvert('number', (v) => (v as num).toInt()), - downloadUrl: $checkedConvert('download_url', (v) => v as String), - hash: $checkedConvert('hash', (v) => v as String), - hashSignature: $checkedConvert('hash_signature', (v) => v as String?), - ); - return val; - }, - fieldKeyMap: const { - 'downloadUrl': 'download_url', - 'hashSignature': 'hash_signature', - }, - ); - -Map _$PatchCheckMetadataToJson(PatchCheckMetadata instance) => - { - 'number': instance.number, - 'download_url': instance.downloadUrl, - 'hash': instance.hash, - 'hash_signature': ?instance.hashSignature, - }; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/promote_patch/promote_patch.dart b/packages/shorebird_code_push_protocol/lib/src/messages/promote_patch/promote_patch.dart deleted file mode 100644 index 426adc5f..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/promote_patch/promote_patch.dart +++ /dev/null @@ -1 +0,0 @@ -export 'promote_patch_request.dart'; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/promote_patch/promote_patch_request.dart b/packages/shorebird_code_push_protocol/lib/src/messages/promote_patch/promote_patch_request.dart index d6f6cb85..06c15385 100644 --- a/packages/shorebird_code_push_protocol/lib/src/messages/promote_patch/promote_patch_request.dart +++ b/packages/shorebird_code_push_protocol/lib/src/messages/promote_patch/promote_patch_request.dart @@ -1,25 +1,63 @@ -import 'package:json_annotation/json_annotation.dart'; - -part 'promote_patch_request.g.dart'; +import 'package:meta/meta.dart'; +import 'package:shorebird_code_push_protocol/model_helpers.dart'; /// {@template promote_patch_request} -/// The request body for POST /api/v1/patches/promote +/// The request body for POST /apps/{appId}/patches/promote. /// {@endtemplate} -@JsonSerializable() +@immutable class PromotePatchRequest { /// {@macro promote_patch_request} - const PromotePatchRequest({required this.patchId, required this.channelId}); + const PromotePatchRequest({ + required this.patchId, + required this.channelId, + }); - /// Converts a `Map` to a [PromotePatchRequest] - factory PromotePatchRequest.fromJson(Map json) => - _$PromotePatchRequestFromJson(json); + /// Converts a `Map` to a [PromotePatchRequest]. + factory PromotePatchRequest.fromJson(Map json) { + return parseFromJson( + 'PromotePatchRequest', + json, + () => PromotePatchRequest( + patchId: json['patch_id'] as int, + channelId: json['channel_id'] as int, + ), + ); + } - /// Converts a [PromotePatchRequest] to a `Map` - Map toJson() => _$PromotePatchRequestToJson(this); + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static PromotePatchRequest? maybeFromJson(Map? json) { + if (json == null) { + return null; + } + return PromotePatchRequest.fromJson(json); + } /// The ID of the patch. final int patchId; /// The ID of the channel. final int channelId; + + /// Converts a [PromotePatchRequest] to a `Map`. + Map toJson() { + return { + 'patch_id': patchId, + 'channel_id': channelId, + }; + } + + @override + int get hashCode => Object.hashAll([ + patchId, + channelId, + ]); + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is PromotePatchRequest && + patchId == other.patchId && + channelId == other.channelId; + } } diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/promote_patch/promote_patch_request.g.dart b/packages/shorebird_code_push_protocol/lib/src/messages/promote_patch/promote_patch_request.g.dart deleted file mode 100644 index 5b5178ff..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/promote_patch/promote_patch_request.g.dart +++ /dev/null @@ -1,30 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ignore_for_file: implicit_dynamic_parameter, require_trailing_commas, cast_nullable_to_non_nullable, lines_longer_than_80_chars - -part of 'promote_patch_request.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -PromotePatchRequest _$PromotePatchRequestFromJson(Map json) => - $checkedCreate( - 'PromotePatchRequest', - json, - ($checkedConvert) { - final val = PromotePatchRequest( - patchId: $checkedConvert('patch_id', (v) => (v as num).toInt()), - channelId: $checkedConvert('channel_id', (v) => (v as num).toInt()), - ); - return val; - }, - fieldKeyMap: const {'patchId': 'patch_id', 'channelId': 'channel_id'}, - ); - -Map _$PromotePatchRequestToJson( - PromotePatchRequest instance, -) => { - 'patch_id': instance.patchId, - 'channel_id': instance.channelId, -}; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/update_app_collaborator/update_app_collaborator.dart b/packages/shorebird_code_push_protocol/lib/src/messages/update_app_collaborator/update_app_collaborator.dart deleted file mode 100644 index 0ac6396b..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/update_app_collaborator/update_app_collaborator.dart +++ /dev/null @@ -1 +0,0 @@ -export 'update_app_collaborator_request.dart'; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/update_app_collaborator/update_app_collaborator_request.dart b/packages/shorebird_code_push_protocol/lib/src/messages/update_app_collaborator/update_app_collaborator_request.dart index 3ee0335d..633ae741 100644 --- a/packages/shorebird_code_push_protocol/lib/src/messages/update_app_collaborator/update_app_collaborator_request.dart +++ b/packages/shorebird_code_push_protocol/lib/src/messages/update_app_collaborator/update_app_collaborator_request.dart @@ -1,24 +1,55 @@ -import 'package:json_annotation/json_annotation.dart'; -import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; - -part 'update_app_collaborator_request.g.dart'; +import 'package:meta/meta.dart'; +import 'package:shorebird_code_push_protocol/model_helpers.dart'; +import 'package:shorebird_code_push_protocol/src/models/app_collaborator_role.dart'; /// {@template update_app_collaborator_request} -/// The request body for -/// PATCH /api/v1/apps/:appId/collaborators/:collaboratorId +/// The request body for PATCH /apps/{appId}/collaborators/{collaboratorId}. /// {@endtemplate} -@JsonSerializable() +@immutable class UpdateAppCollaboratorRequest { /// {@macro update_app_collaborator_request} - const UpdateAppCollaboratorRequest({required this.role}); + const UpdateAppCollaboratorRequest({ + required this.role, + }); /// Converts a `Map` to a [UpdateAppCollaboratorRequest]. - factory UpdateAppCollaboratorRequest.fromJson(Map json) => - _$UpdateAppCollaboratorRequestFromJson(json); + factory UpdateAppCollaboratorRequest.fromJson(Map json) { + return parseFromJson( + 'UpdateAppCollaboratorRequest', + json, + () => UpdateAppCollaboratorRequest( + role: AppCollaboratorRole.fromJson(json['role'] as String), + ), + ); + } + + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static UpdateAppCollaboratorRequest? maybeFromJson( + Map? json, + ) { + if (json == null) { + return null; + } + return UpdateAppCollaboratorRequest.fromJson(json); + } + + /// A role a user can have on a specific app. + final AppCollaboratorRole role; /// Converts a [UpdateAppCollaboratorRequest] to a `Map`. - Map toJson() => _$UpdateAppCollaboratorRequestToJson(this); + Map toJson() { + return { + 'role': role.toJson(), + }; + } - /// The new role for the collaborator. - final AppCollaboratorRole role; + @override + int get hashCode => role.hashCode; + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is UpdateAppCollaboratorRequest && role == other.role; + } } diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/update_app_collaborator/update_app_collaborator_request.g.dart b/packages/shorebird_code_push_protocol/lib/src/messages/update_app_collaborator/update_app_collaborator_request.g.dart deleted file mode 100644 index 98a7bbbb..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/update_app_collaborator/update_app_collaborator_request.g.dart +++ /dev/null @@ -1,30 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ignore_for_file: implicit_dynamic_parameter, require_trailing_commas, cast_nullable_to_non_nullable, lines_longer_than_80_chars - -part of 'update_app_collaborator_request.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -UpdateAppCollaboratorRequest _$UpdateAppCollaboratorRequestFromJson( - Map json, -) => $checkedCreate('UpdateAppCollaboratorRequest', json, ($checkedConvert) { - final val = UpdateAppCollaboratorRequest( - role: $checkedConvert( - 'role', - (v) => $enumDecode(_$AppCollaboratorRoleEnumMap, v), - ), - ); - return val; -}); - -Map _$UpdateAppCollaboratorRequestToJson( - UpdateAppCollaboratorRequest instance, -) => {'role': _$AppCollaboratorRoleEnumMap[instance.role]!}; - -const _$AppCollaboratorRoleEnumMap = { - AppCollaboratorRole.admin: 'admin', - AppCollaboratorRole.developer: 'developer', -}; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/update_patch/update_patch.dart b/packages/shorebird_code_push_protocol/lib/src/messages/update_patch/update_patch.dart deleted file mode 100644 index 9c723ed9..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/update_patch/update_patch.dart +++ /dev/null @@ -1 +0,0 @@ -export 'update_patch_request.dart'; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/update_patch/update_patch_request.dart b/packages/shorebird_code_push_protocol/lib/src/messages/update_patch/update_patch_request.dart index 2fd4a97a..7e2c4741 100644 --- a/packages/shorebird_code_push_protocol/lib/src/messages/update_patch/update_patch_request.dart +++ b/packages/shorebird_code_push_protocol/lib/src/messages/update_patch/update_patch_request.dart @@ -1,26 +1,53 @@ -import 'package:json_annotation/json_annotation.dart'; -import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; - -part 'update_patch_request.g.dart'; +import 'package:meta/meta.dart'; +import 'package:shorebird_code_push_protocol/model_helpers.dart'; /// {@template update_patch_request} -/// Request body for PATCH -/// `api/v1/apps/:appId/releases/:releaseId/patch/:patchId` requests. +/// The request body for PATCH +/// /apps/{appId}/releases/{releaseId}/patches/{patchId}. /// {@endtemplate} -@JsonSerializable() +@immutable class UpdatePatchRequest { /// {@macro update_patch_request} - const UpdatePatchRequest({this.notes}); + const UpdatePatchRequest({ + this.notes, + }); /// Converts a `Map` to a [UpdatePatchRequest]. - factory UpdatePatchRequest.fromJson(Json json) => - _$UpdatePatchRequestFromJson(json); + factory UpdatePatchRequest.fromJson(Map json) { + return parseFromJson( + 'UpdatePatchRequest', + json, + () => UpdatePatchRequest( + notes: json['notes'] as String?, + ), + ); + } + + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static UpdatePatchRequest? maybeFromJson(Map? json) { + if (json == null) { + return null; + } + return UpdatePatchRequest.fromJson(json); + } + + /// Freeform notes about the patch. If null, notes are unchanged. + final String? notes; /// Converts a [UpdatePatchRequest] to a `Map`. - Json toJson() => _$UpdatePatchRequestToJson(this); + Map toJson() { + return { + 'notes': notes, + }; + } - /// Notes about the patch. This is a free-form field that can be used to - /// store additional information about the patch. If null, the notes will - /// not be updated. - final String? notes; + @override + int get hashCode => notes.hashCode; + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is UpdatePatchRequest && notes == other.notes; + } } diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/update_patch/update_patch_request.g.dart b/packages/shorebird_code_push_protocol/lib/src/messages/update_patch/update_patch_request.g.dart deleted file mode 100644 index 22ec62c3..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/update_patch/update_patch_request.g.dart +++ /dev/null @@ -1,20 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ignore_for_file: implicit_dynamic_parameter, require_trailing_commas, cast_nullable_to_non_nullable, lines_longer_than_80_chars - -part of 'update_patch_request.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -UpdatePatchRequest _$UpdatePatchRequestFromJson(Map json) => - $checkedCreate('UpdatePatchRequest', json, ($checkedConvert) { - final val = UpdatePatchRequest( - notes: $checkedConvert('notes', (v) => v as String?), - ); - return val; - }); - -Map _$UpdatePatchRequestToJson(UpdatePatchRequest instance) => - {'notes': instance.notes}; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/update_release/update_release.dart b/packages/shorebird_code_push_protocol/lib/src/messages/update_release/update_release.dart deleted file mode 100644 index 0d320c0a..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/update_release/update_release.dart +++ /dev/null @@ -1 +0,0 @@ -export 'update_release_request.dart'; diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/update_release/update_release_request.dart b/packages/shorebird_code_push_protocol/lib/src/messages/update_release/update_release_request.dart index e004461d..22555cef 100644 --- a/packages/shorebird_code_push_protocol/lib/src/messages/update_release/update_release_request.dart +++ b/packages/shorebird_code_push_protocol/lib/src/messages/update_release/update_release_request.dart @@ -1,12 +1,12 @@ -import 'package:json_annotation/json_annotation.dart'; -import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; - -part 'update_release_request.g.dart'; +import 'package:meta/meta.dart'; +import 'package:shorebird_code_push_protocol/model_helpers.dart'; +import 'package:shorebird_code_push_protocol/src/models/release_platform.dart'; +import 'package:shorebird_code_push_protocol/src/models/release_status.dart'; /// {@template update_release_request} -/// Request body for PUT `api/v1/release/:id` requests. +/// The request body for PATCH /apps/{appId}/releases/{releaseId}. /// {@endtemplate} -@JsonSerializable() +@immutable class UpdateReleaseRequest { /// {@macro update_release_request} const UpdateReleaseRequest({ @@ -17,25 +17,70 @@ class UpdateReleaseRequest { }); /// Converts a `Map` to a [UpdateReleaseRequest]. - factory UpdateReleaseRequest.fromJson(Json json) => - _$UpdateReleaseRequestFromJson(json); + factory UpdateReleaseRequest.fromJson(Map json) { + return parseFromJson( + 'UpdateReleaseRequest', + json, + () => UpdateReleaseRequest( + status: ReleaseStatus.maybeFromJson(json['status'] as String?), + platform: ReleasePlatform.maybeFromJson(json['platform'] as String?), + metadata: (json['metadata'] as Map?)?.map( + MapEntry.new, + ), + notes: json['notes'] as String?, + ), + ); + } - /// Converts a [UpdateReleaseRequest] to a `Map`. - Json toJson() => _$UpdateReleaseRequestToJson(this); + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static UpdateReleaseRequest? maybeFromJson(Map? json) { + if (json == null) { + return null; + } + return UpdateReleaseRequest.fromJson(json); + } - /// The desired status of the release. If provided, [platform] must also be - /// provided If null, the status will not be updated. + /// The status of a release. final ReleaseStatus? status; - /// The platform of the release. If provided, [status] must also be provided. + /// A platform to which a Shorebird release can be deployed. final ReleasePlatform? platform; - /// Additional information about the command that was run to update the - /// release and the environment in which it was run. - final Json? metadata; + /// Additional information about the command that was run to + /// update the release and the environment it was run in. + final Map? metadata; /// Notes about the release. This is a free-form field that can be used to /// store additional information about the release. If null, the notes will /// not be updated. final String? notes; + + /// Converts a [UpdateReleaseRequest] to a `Map`. + Map toJson() { + return { + 'status': status?.toJson(), + 'platform': platform?.toJson(), + 'metadata': metadata, + 'notes': notes, + }; + } + + @override + int get hashCode => Object.hashAll([ + status, + platform, + mapHash(metadata), + notes, + ]); + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is UpdateReleaseRequest && + status == other.status && + platform == other.platform && + mapsEqual(metadata, other.metadata) && + notes == other.notes; + } } diff --git a/packages/shorebird_code_push_protocol/lib/src/messages/update_release/update_release_request.g.dart b/packages/shorebird_code_push_protocol/lib/src/messages/update_release/update_release_request.g.dart deleted file mode 100644 index cf7fc2d0..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/messages/update_release/update_release_request.g.dart +++ /dev/null @@ -1,49 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ignore_for_file: implicit_dynamic_parameter, require_trailing_commas, cast_nullable_to_non_nullable, lines_longer_than_80_chars - -part of 'update_release_request.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -UpdateReleaseRequest _$UpdateReleaseRequestFromJson( - Map json, -) => $checkedCreate('UpdateReleaseRequest', json, ($checkedConvert) { - final val = UpdateReleaseRequest( - status: $checkedConvert( - 'status', - (v) => $enumDecodeNullable(_$ReleaseStatusEnumMap, v), - ), - platform: $checkedConvert( - 'platform', - (v) => $enumDecodeNullable(_$ReleasePlatformEnumMap, v), - ), - metadata: $checkedConvert('metadata', (v) => v as Map?), - notes: $checkedConvert('notes', (v) => v as String?), - ); - return val; -}); - -Map _$UpdateReleaseRequestToJson( - UpdateReleaseRequest instance, -) => { - 'status': _$ReleaseStatusEnumMap[instance.status], - 'platform': _$ReleasePlatformEnumMap[instance.platform], - 'metadata': instance.metadata, - 'notes': instance.notes, -}; - -const _$ReleaseStatusEnumMap = { - ReleaseStatus.draft: 'draft', - ReleaseStatus.active: 'active', -}; - -const _$ReleasePlatformEnumMap = { - ReleasePlatform.android: 'android', - ReleasePlatform.ios: 'ios', - ReleasePlatform.linux: 'linux', - ReleasePlatform.macos: 'macos', - ReleasePlatform.windows: 'windows', -}; diff --git a/packages/shorebird_code_push_protocol/lib/src/models/app.dart b/packages/shorebird_code_push_protocol/lib/src/models/app.dart index 8bdc7d3e..d295184d 100644 --- a/packages/shorebird_code_push_protocol/lib/src/models/app.dart +++ b/packages/shorebird_code_push_protocol/lib/src/models/app.dart @@ -1,24 +1,61 @@ -import 'package:json_annotation/json_annotation.dart'; - -part 'app.g.dart'; +import 'package:meta/meta.dart'; +import 'package:shorebird_code_push_protocol/model_helpers.dart'; /// {@template app} /// The application downloaded and run on various devices/platforms. /// {@endtemplate} -@JsonSerializable() +@immutable class App { /// {@macro app} - const App({required this.id, required this.displayName}); + const App({ + required this.id, + required this.displayName, + }); - /// Converts a `Map` to an [App] - factory App.fromJson(Map json) => _$AppFromJson(json); + /// Converts a `Map` to an [App]. + factory App.fromJson(Map json) { + return parseFromJson( + 'App', + json, + () => App( + id: json['id'] as String, + displayName: json['display_name'] as String, + ), + ); + } - /// Converts a [App] to a `Map` - Map toJson() => _$AppToJson(this); + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static App? maybeFromJson(Map? json) { + if (json == null) { + return null; + } + return App.fromJson(json); + } /// The ID of the app. final String id; /// The display name of the app. final String displayName; + + /// Converts an [App] to a `Map`. + Map toJson() { + return { + 'id': id, + 'display_name': displayName, + }; + } + + @override + int get hashCode => Object.hashAll([ + id, + displayName, + ]); + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is App && id == other.id && displayName == other.displayName; + } } diff --git a/packages/shorebird_code_push_protocol/lib/src/models/app.g.dart b/packages/shorebird_code_push_protocol/lib/src/models/app.g.dart deleted file mode 100644 index d5e42e59..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/models/app.g.dart +++ /dev/null @@ -1,23 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ignore_for_file: implicit_dynamic_parameter, require_trailing_commas, cast_nullable_to_non_nullable, lines_longer_than_80_chars - -part of 'app.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -App _$AppFromJson(Map json) => - $checkedCreate('App', json, ($checkedConvert) { - final val = App( - id: $checkedConvert('id', (v) => v as String), - displayName: $checkedConvert('display_name', (v) => v as String), - ); - return val; - }, fieldKeyMap: const {'displayName': 'display_name'}); - -Map _$AppToJson(App instance) => { - 'id': instance.id, - 'display_name': instance.displayName, -}; diff --git a/packages/shorebird_code_push_protocol/lib/src/models/app_collaborator_role.dart b/packages/shorebird_code_push_protocol/lib/src/models/app_collaborator_role.dart index 55fb1dd8..6320fa30 100644 --- a/packages/shorebird_code_push_protocol/lib/src/models/app_collaborator_role.dart +++ b/packages/shorebird_code_push_protocol/lib/src/models/app_collaborator_role.dart @@ -1,19 +1,41 @@ -/// {@template app_collaborator_role} -/// The role a user has for a specific app. Roles are associated with different -/// permission levels. -/// {@endtemplate} +/// A role a user can have on a specific app. enum AppCollaboratorRole { - /// A user with this role can perform all available actions on apps, releases, - /// patches, channels, and collaborators. - admin('admin'), + /// A user with this role can perform all available actions on apps, + /// releases, patches, channels, and collaborators. + admin._('admin'), /// A user with this role can manage releases and patches, but cannot manage /// collaborators or the application itself. - developer('developer'); + developer._('developer'); - /// {@macro app_collaborator_role} - const AppCollaboratorRole(this.name); + const AppCollaboratorRole._(this.value); - /// The name of the role. - final String name; + /// Creates a AppCollaboratorRole from a json string. + factory AppCollaboratorRole.fromJson(String json) { + return AppCollaboratorRole.values.firstWhere( + (value) => value.value == json, + orElse: () => + throw FormatException('Unknown AppCollaboratorRole value: $json'), + ); + } + + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static AppCollaboratorRole? maybeFromJson(String? json) { + if (json == null) { + return null; + } + return AppCollaboratorRole.fromJson(json); + } + + /// The value of the enum, as a string. This is the exact value + /// from the OpenAPI spec and will be used for network transport. + final String value; + + /// Converts the enum to a json string. + String toJson() => value; + + /// Returns the string value of the enum. + @override + String toString() => value; } diff --git a/packages/shorebird_code_push_protocol/lib/src/models/app_metadata.dart b/packages/shorebird_code_push_protocol/lib/src/models/app_metadata.dart index 3647a320..63e8c7ec 100644 --- a/packages/shorebird_code_push_protocol/lib/src/models/app_metadata.dart +++ b/packages/shorebird_code_push_protocol/lib/src/models/app_metadata.dart @@ -1,13 +1,11 @@ -import 'package:equatable/equatable.dart'; -import 'package:json_annotation/json_annotation.dart'; - -part 'app_metadata.g.dart'; +import 'package:meta/meta.dart'; +import 'package:shorebird_code_push_protocol/model_helpers.dart'; /// {@template app_metadata} /// A single app which contains zero or more releases. /// {@endtemplate} -@JsonSerializable() -class AppMetadata extends Equatable { +@immutable +class AppMetadata { /// {@macro app_metadata} const AppMetadata({ required this.appId, @@ -18,12 +16,30 @@ class AppMetadata extends Equatable { this.latestPatchNumber, }); - /// Converts a `Map` to an [AppMetadata] - factory AppMetadata.fromJson(Map json) => - _$AppMetadataFromJson(json); + /// Converts a `Map` to an [AppMetadata]. + factory AppMetadata.fromJson(Map json) { + return parseFromJson( + 'AppMetadata', + json, + () => AppMetadata( + appId: json['app_id'] as String, + displayName: json['display_name'] as String, + latestReleaseVersion: json['latest_release_version'] as String?, + latestPatchNumber: json['latest_patch_number'] as int?, + createdAt: DateTime.parse(json['created_at'] as String), + updatedAt: DateTime.parse(json['updated_at'] as String), + ), + ); + } - /// Converts a [AppMetadata] to a `Map` - Map toJson() => _$AppMetadataToJson(this); + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static AppMetadata? maybeFromJson(Map? json) { + if (json == null) { + return null; + } + return AppMetadata.fromJson(json); + } /// The ID of the app. final String appId; @@ -43,13 +59,37 @@ class AppMetadata extends Equatable { /// The date and time the app was last updated. final DateTime updatedAt; + /// Converts an [AppMetadata] to a `Map`. + Map toJson() { + return { + 'app_id': appId, + 'display_name': displayName, + 'latest_release_version': latestReleaseVersion, + 'latest_patch_number': latestPatchNumber, + 'created_at': createdAt.toIso8601String(), + 'updated_at': updatedAt.toIso8601String(), + }; + } + @override - List get props => [ + int get hashCode => Object.hashAll([ appId, displayName, latestReleaseVersion, latestPatchNumber, createdAt, updatedAt, - ]; + ]); + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is AppMetadata && + appId == other.appId && + displayName == other.displayName && + latestReleaseVersion == other.latestReleaseVersion && + latestPatchNumber == other.latestPatchNumber && + createdAt == other.createdAt && + updatedAt == other.updatedAt; + } } diff --git a/packages/shorebird_code_push_protocol/lib/src/models/app_metadata.g.dart b/packages/shorebird_code_push_protocol/lib/src/models/app_metadata.g.dart deleted file mode 100644 index f2a9ecd7..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/models/app_metadata.g.dart +++ /dev/null @@ -1,55 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ignore_for_file: implicit_dynamic_parameter, require_trailing_commas, cast_nullable_to_non_nullable, lines_longer_than_80_chars - -part of 'app_metadata.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -AppMetadata _$AppMetadataFromJson(Map json) => $checkedCreate( - 'AppMetadata', - json, - ($checkedConvert) { - final val = AppMetadata( - appId: $checkedConvert('app_id', (v) => v as String), - displayName: $checkedConvert('display_name', (v) => v as String), - createdAt: $checkedConvert( - 'created_at', - (v) => DateTime.parse(v as String), - ), - updatedAt: $checkedConvert( - 'updated_at', - (v) => DateTime.parse(v as String), - ), - latestReleaseVersion: $checkedConvert( - 'latest_release_version', - (v) => v as String?, - ), - latestPatchNumber: $checkedConvert( - 'latest_patch_number', - (v) => (v as num?)?.toInt(), - ), - ); - return val; - }, - fieldKeyMap: const { - 'appId': 'app_id', - 'displayName': 'display_name', - 'createdAt': 'created_at', - 'updatedAt': 'updated_at', - 'latestReleaseVersion': 'latest_release_version', - 'latestPatchNumber': 'latest_patch_number', - }, -); - -Map _$AppMetadataToJson(AppMetadata instance) => - { - 'app_id': instance.appId, - 'display_name': instance.displayName, - 'latest_release_version': instance.latestReleaseVersion, - 'latest_patch_number': instance.latestPatchNumber, - 'created_at': instance.createdAt.toIso8601String(), - 'updated_at': instance.updatedAt.toIso8601String(), - }; diff --git a/packages/shorebird_code_push_protocol/lib/src/models/channel.dart b/packages/shorebird_code_push_protocol/lib/src/models/channel.dart index eabafbda..4a2c7b3b 100644 --- a/packages/shorebird_code_push_protocol/lib/src/models/channel.dart +++ b/packages/shorebird_code_push_protocol/lib/src/models/channel.dart @@ -1,25 +1,43 @@ -import 'package:json_annotation/json_annotation.dart'; - -part 'channel.g.dart'; +import 'package:meta/meta.dart'; +import 'package:shorebird_code_push_protocol/model_helpers.dart'; /// {@template channel} /// A tag used to manage the subset of installs that receive a patch. -/// By default, a "stable" channel is created and -/// used by devices to query for available patches. +/// By default a "stable" channel is created and used by devices to +/// query for available patches. /// {@endtemplate} -@JsonSerializable() +@immutable class Channel { /// {@macro channel} - const Channel({required this.id, required this.appId, required this.name}); + const Channel({ + required this.id, + required this.appId, + required this.name, + }); - /// Converts a `Map` to a [Channel] - factory Channel.fromJson(Map json) => - _$ChannelFromJson(json); + /// Converts a `Map` to a [Channel]. + factory Channel.fromJson(Map json) { + return parseFromJson( + 'Channel', + json, + () => Channel( + id: json['id'] as int, + appId: json['app_id'] as String, + name: json['name'] as String, + ), + ); + } - /// Converts a [Channel] to a `Map` - Map toJson() => _$ChannelToJson(this); + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static Channel? maybeFromJson(Map? json) { + if (json == null) { + return null; + } + return Channel.fromJson(json); + } - /// The ID of the channel; + /// The ID of the channel. final int id; /// The ID of the app. @@ -27,4 +45,29 @@ class Channel { /// The channel name. final String name; + + /// Converts a [Channel] to a `Map`. + Map toJson() { + return { + 'id': id, + 'app_id': appId, + 'name': name, + }; + } + + @override + int get hashCode => Object.hashAll([ + id, + appId, + name, + ]); + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is Channel && + id == other.id && + appId == other.appId && + name == other.name; + } } diff --git a/packages/shorebird_code_push_protocol/lib/src/models/channel.g.dart b/packages/shorebird_code_push_protocol/lib/src/models/channel.g.dart deleted file mode 100644 index 6e9858eb..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/models/channel.g.dart +++ /dev/null @@ -1,25 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ignore_for_file: implicit_dynamic_parameter, require_trailing_commas, cast_nullable_to_non_nullable, lines_longer_than_80_chars - -part of 'channel.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -Channel _$ChannelFromJson(Map json) => - $checkedCreate('Channel', json, ($checkedConvert) { - final val = Channel( - id: $checkedConvert('id', (v) => (v as num).toInt()), - appId: $checkedConvert('app_id', (v) => v as String), - name: $checkedConvert('name', (v) => v as String), - ); - return val; - }, fieldKeyMap: const {'appId': 'app_id'}); - -Map _$ChannelToJson(Channel instance) => { - 'id': instance.id, - 'app_id': instance.appId, - 'name': instance.name, -}; diff --git a/packages/shorebird_code_push_protocol/lib/src/models/error_response.dart b/packages/shorebird_code_push_protocol/lib/src/models/error_response.dart deleted file mode 100644 index 20046384..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/models/error_response.dart +++ /dev/null @@ -1,32 +0,0 @@ -import 'package:json_annotation/json_annotation.dart'; - -part 'error_response.g.dart'; - -/// {@template error_response} -/// Standard error response body from the Shorebird Code Push API. -/// {@endtemplate} -@JsonSerializable() -class ErrorResponse { - /// {@macro error_response} - const ErrorResponse({ - required this.code, - required this.message, - this.details, - }); - - /// Converts a [Map] to [ErrorResponse]. - factory ErrorResponse.fromJson(Map json) => - _$ErrorResponseFromJson(json); - - /// Converts a [ErrorResponse] to [Map]. - Map toJson() => _$ErrorResponseToJson(this); - - /// The unique error code. - final String code; - - /// Human-readable error message. - final String message; - - /// Optional details associated with the error. - final String? details; -} diff --git a/packages/shorebird_code_push_protocol/lib/src/models/error_response.g.dart b/packages/shorebird_code_push_protocol/lib/src/models/error_response.g.dart deleted file mode 100644 index f8dbed42..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/models/error_response.g.dart +++ /dev/null @@ -1,26 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ignore_for_file: implicit_dynamic_parameter, require_trailing_commas, cast_nullable_to_non_nullable, lines_longer_than_80_chars - -part of 'error_response.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -ErrorResponse _$ErrorResponseFromJson(Map json) => - $checkedCreate('ErrorResponse', json, ($checkedConvert) { - final val = ErrorResponse( - code: $checkedConvert('code', (v) => v as String), - message: $checkedConvert('message', (v) => v as String), - details: $checkedConvert('details', (v) => v as String?), - ); - return val; - }); - -Map _$ErrorResponseToJson(ErrorResponse instance) => - { - 'code': instance.code, - 'message': instance.message, - 'details': instance.details, - }; diff --git a/packages/shorebird_code_push_protocol/lib/src/models/models.dart b/packages/shorebird_code_push_protocol/lib/src/models/models.dart deleted file mode 100644 index 46a6db5f..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/models/models.dart +++ /dev/null @@ -1,19 +0,0 @@ -export 'app.dart'; -export 'app_collaborator_role.dart'; -export 'app_metadata.dart'; -export 'auth_provider.dart'; -export 'channel.dart'; -export 'error_response.dart'; -export 'organization.dart'; -export 'organization_membership.dart'; -export 'organization_user.dart'; -export 'patch.dart'; -export 'patch_artifact.dart'; -export 'private_user.dart'; -export 'public_user.dart'; -export 'release.dart'; -export 'release_artifact.dart'; -export 'release_patch.dart'; -export 'release_platform.dart'; -export 'release_status.dart'; -export 'role.dart'; diff --git a/packages/shorebird_code_push_protocol/lib/src/models/organization.dart b/packages/shorebird_code_push_protocol/lib/src/models/organization.dart index aee49eda..74cf1b8f 100644 --- a/packages/shorebird_code_push_protocol/lib/src/models/organization.dart +++ b/packages/shorebird_code_push_protocol/lib/src/models/organization.dart @@ -1,28 +1,13 @@ -import 'package:equatable/equatable.dart'; -import 'package:json_annotation/json_annotation.dart'; import 'package:meta/meta.dart'; - -part 'organization.g.dart'; - -/// {@template organization_type} -/// Distinguishes between automatically created organizations that are limited -/// to a single user and organizations that support multiple users. -/// {@endtemplate} -enum OrganizationType { - /// A personal organization is created for every user for their own apps. - personal, - - /// A team organization is created for multiple users to collaborate on apps. - team, -} +import 'package:shorebird_code_push_protocol/model_helpers.dart'; +import 'package:shorebird_code_push_protocol/src/models/organization_type.dart'; /// {@template organization} -/// An Organization groups users and apps together. Organizations can be -/// personal (single-user) or team (multi-user). Organizations have exactly one -/// owner, but can have multiple admins and members. +/// An organization groups users and apps together. Organizations +/// can be personal (single-user) or team (multi-user). /// {@endtemplate} -@JsonSerializable() -class Organization extends Equatable { +@immutable +class Organization { /// {@macro organization} const Organization({ required this.id, @@ -32,30 +17,31 @@ class Organization extends Equatable { required this.updatedAt, }); - /// Converts a [Map] to an [Organization]. - factory Organization.fromJson(Map json) => - _$OrganizationFromJson(json); + /// Converts a `Map` to an [Organization]. + factory Organization.fromJson(Map json) { + return parseFromJson( + 'Organization', + json, + () => Organization( + id: json['id'] as int, + name: json['name'] as String, + organizationType: OrganizationType.fromJson( + json['organization_type'] as String, + ), + createdAt: DateTime.parse(json['created_at'] as String), + updatedAt: DateTime.parse(json['updated_at'] as String), + ), + ); + } - // coverage:ignore-start - /// Constructs an organization with arbitrary default values for testing. - @visibleForTesting - factory Organization.forTest({ - int id = 42, - String name = 'Test Organization', - OrganizationType organizationType = OrganizationType.personal, - DateTime? createdAt, - DateTime? updatedAt, - }) => Organization( - id: id, - name: name, - organizationType: organizationType, - createdAt: createdAt ?? DateTime.now(), - updatedAt: updatedAt ?? DateTime.now(), - ); - // coverage:ignore-end - - /// Converts this [Organization] to a JSON map - Map toJson() => _$OrganizationToJson(this); + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static Organization? maybeFromJson(Map? json) { + if (json == null) { + return null; + } + return Organization.fromJson(json); + } /// The unique identifier for the organization. final int id; @@ -63,7 +49,8 @@ class Organization extends Equatable { /// The name of the organization. final String name; - /// The type of organization. + /// Distinguishes personal organizations (single-user) from team + /// organizations (multi-user). final OrganizationType organizationType; /// When this organization was created. @@ -72,6 +59,34 @@ class Organization extends Equatable { /// When this organization was last updated. final DateTime updatedAt; + /// Converts an [Organization] to a `Map`. + Map toJson() { + return { + 'id': id, + 'name': name, + 'organization_type': organizationType.toJson(), + 'created_at': createdAt.toIso8601String(), + 'updated_at': updatedAt.toIso8601String(), + }; + } + @override - List get props => [id, name, organizationType, createdAt, updatedAt]; + int get hashCode => Object.hashAll([ + id, + name, + organizationType, + createdAt, + updatedAt, + ]); + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is Organization && + id == other.id && + name == other.name && + organizationType == other.organizationType && + createdAt == other.createdAt && + updatedAt == other.updatedAt; + } } diff --git a/packages/shorebird_code_push_protocol/lib/src/models/organization.g.dart b/packages/shorebird_code_push_protocol/lib/src/models/organization.g.dart deleted file mode 100644 index fe5ecda3..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/models/organization.g.dart +++ /dev/null @@ -1,54 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ignore_for_file: implicit_dynamic_parameter, require_trailing_commas, cast_nullable_to_non_nullable, lines_longer_than_80_chars - -part of 'organization.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -Organization _$OrganizationFromJson(Map json) => - $checkedCreate( - 'Organization', - json, - ($checkedConvert) { - final val = Organization( - id: $checkedConvert('id', (v) => (v as num).toInt()), - name: $checkedConvert('name', (v) => v as String), - organizationType: $checkedConvert( - 'organization_type', - (v) => $enumDecode(_$OrganizationTypeEnumMap, v), - ), - createdAt: $checkedConvert( - 'created_at', - (v) => DateTime.parse(v as String), - ), - updatedAt: $checkedConvert( - 'updated_at', - (v) => DateTime.parse(v as String), - ), - ); - return val; - }, - fieldKeyMap: const { - 'organizationType': 'organization_type', - 'createdAt': 'created_at', - 'updatedAt': 'updated_at', - }, - ); - -Map _$OrganizationToJson( - Organization instance, -) => { - 'id': instance.id, - 'name': instance.name, - 'organization_type': _$OrganizationTypeEnumMap[instance.organizationType]!, - 'created_at': instance.createdAt.toIso8601String(), - 'updated_at': instance.updatedAt.toIso8601String(), -}; - -const _$OrganizationTypeEnumMap = { - OrganizationType.personal: 'personal', - OrganizationType.team: 'team', -}; diff --git a/packages/shorebird_code_push_protocol/lib/src/models/organization_membership.dart b/packages/shorebird_code_push_protocol/lib/src/models/organization_membership.dart index 6ead8d75..c4da68c2 100644 --- a/packages/shorebird_code_push_protocol/lib/src/models/organization_membership.dart +++ b/packages/shorebird_code_push_protocol/lib/src/models/organization_membership.dart @@ -1,33 +1,68 @@ -import 'package:equatable/equatable.dart'; -import 'package:json_annotation/json_annotation.dart'; -import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; - -part 'organization_membership.g.dart'; +import 'package:meta/meta.dart'; +import 'package:shorebird_code_push_protocol/model_helpers.dart'; +import 'package:shorebird_code_push_protocol/src/models/organization.dart'; +import 'package:shorebird_code_push_protocol/src/models/role.dart'; /// {@template organization_membership} -/// An organization and the current user's role in that organization. +/// An organization and the current user's role in it. /// {@endtemplate} -@JsonSerializable() -class OrganizationMembership extends Equatable { +@immutable +class OrganizationMembership { /// {@macro organization_membership} const OrganizationMembership({ required this.organization, required this.role, }); - /// Deserializes the [OrganizationMembership] from aJSON map. - factory OrganizationMembership.fromJson(Map json) => - _$OrganizationMembershipFromJson(json); + /// Converts a `Map` to an [OrganizationMembership]. + factory OrganizationMembership.fromJson(Map json) { + return parseFromJson( + 'OrganizationMembership', + json, + () => OrganizationMembership( + organization: Organization.fromJson( + json['organization'] as Map, + ), + role: Role.fromJson(json['role'] as String), + ), + ); + } - /// Serializes the [OrganizationMembership] to a JSON map. - Map toJson() => _$OrganizationMembershipToJson(this); + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static OrganizationMembership? maybeFromJson(Map? json) { + if (json == null) { + return null; + } + return OrganizationMembership.fromJson(json); + } - /// The organization. + /// An organization groups users and apps together. Organizations + /// can be personal (single-user) or team (multi-user). final Organization organization; - /// The user's role in the organization. + /// A role that a user can have relative to an Organization or App. final Role role; + /// Converts an [OrganizationMembership] to a `Map`. + Map toJson() { + return { + 'organization': organization.toJson(), + 'role': role.toJson(), + }; + } + @override - List get props => [organization, role]; + int get hashCode => Object.hashAll([ + organization, + role, + ]); + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is OrganizationMembership && + organization == other.organization && + role == other.role; + } } diff --git a/packages/shorebird_code_push_protocol/lib/src/models/organization_membership.g.dart b/packages/shorebird_code_push_protocol/lib/src/models/organization_membership.g.dart deleted file mode 100644 index 78185663..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/models/organization_membership.g.dart +++ /dev/null @@ -1,38 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ignore_for_file: implicit_dynamic_parameter, require_trailing_commas, cast_nullable_to_non_nullable, lines_longer_than_80_chars - -part of 'organization_membership.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -OrganizationMembership _$OrganizationMembershipFromJson( - Map json, -) => $checkedCreate('OrganizationMembership', json, ($checkedConvert) { - final val = OrganizationMembership( - organization: $checkedConvert( - 'organization', - (v) => Organization.fromJson(v as Map), - ), - role: $checkedConvert('role', (v) => $enumDecode(_$RoleEnumMap, v)), - ); - return val; -}); - -Map _$OrganizationMembershipToJson( - OrganizationMembership instance, -) => { - 'organization': instance.organization.toJson(), - 'role': _$RoleEnumMap[instance.role]!, -}; - -const _$RoleEnumMap = { - Role.owner: 'owner', - Role.admin: 'admin', - Role.appManager: 'appManager', - Role.developer: 'developer', - Role.viewer: 'viewer', - Role.none: 'none', -}; diff --git a/packages/shorebird_code_push_protocol/lib/src/models/organization_type.dart b/packages/shorebird_code_push_protocol/lib/src/models/organization_type.dart new file mode 100644 index 00000000..56ea123e --- /dev/null +++ b/packages/shorebird_code_push_protocol/lib/src/models/organization_type.dart @@ -0,0 +1,40 @@ +/// Distinguishes personal organizations (single-user) from team +/// organizations (multi-user). +enum OrganizationType { + /// A single-user organization implicitly created with each user account. + personal._('personal'), + + /// A multi-user organization with collaborators. + team._('team'); + + const OrganizationType._(this.value); + + /// Creates a OrganizationType from a json string. + factory OrganizationType.fromJson(String json) { + return OrganizationType.values.firstWhere( + (value) => value.value == json, + orElse: () => + throw FormatException('Unknown OrganizationType value: $json'), + ); + } + + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static OrganizationType? maybeFromJson(String? json) { + if (json == null) { + return null; + } + return OrganizationType.fromJson(json); + } + + /// The value of the enum, as a string. This is the exact value + /// from the OpenAPI spec and will be used for network transport. + final String value; + + /// Converts the enum to a json string. + String toJson() => value; + + /// Returns the string value of the enum. + @override + String toString() => value; +} diff --git a/packages/shorebird_code_push_protocol/lib/src/models/organization_user.dart b/packages/shorebird_code_push_protocol/lib/src/models/organization_user.dart index b0d2cf12..61274d4f 100644 --- a/packages/shorebird_code_push_protocol/lib/src/models/organization_user.dart +++ b/packages/shorebird_code_push_protocol/lib/src/models/organization_user.dart @@ -1,26 +1,65 @@ -import 'package:json_annotation/json_annotation.dart'; -import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; - -part 'organization_user.g.dart'; +import 'package:meta/meta.dart'; +import 'package:shorebird_code_push_protocol/model_helpers.dart'; +import 'package:shorebird_code_push_protocol/src/models/public_user.dart'; +import 'package:shorebird_code_push_protocol/src/models/role.dart'; /// {@template organization_user} -/// A member of an organization and their role in that organization. +/// A member of an organization and their role. /// {@endtemplate} -@JsonSerializable() +@immutable class OrganizationUser { /// {@macro organization_user} - OrganizationUser({required this.user, required this.role}); + const OrganizationUser({ + required this.user, + required this.role, + }); - /// Converts this [OrganizationUser] to a JSON map. - factory OrganizationUser.fromJson(Map json) => - _$OrganizationUserFromJson(json); + /// Converts a `Map` to an [OrganizationUser]. + factory OrganizationUser.fromJson(Map json) { + return parseFromJson( + 'OrganizationUser', + json, + () => OrganizationUser( + user: PublicUser.fromJson(json['user'] as Map), + role: Role.fromJson(json['role'] as String), + ), + ); + } - /// Converts a JSON map to an [OrganizationUser]. - Map toJson() => _$OrganizationUserToJson(this); + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static OrganizationUser? maybeFromJson(Map? json) { + if (json == null) { + return null; + } + return OrganizationUser.fromJson(json); + } - /// The user that is a member of the organization. + /// A Shorebird user with non-sensitive information only. final PublicUser user; - /// The role [user] has in the organization. + /// A role that a user can have relative to an Organization or App. final Role role; + + /// Converts an [OrganizationUser] to a `Map`. + Map toJson() { + return { + 'user': user.toJson(), + 'role': role.toJson(), + }; + } + + @override + int get hashCode => Object.hashAll([ + user, + role, + ]); + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is OrganizationUser && + user == other.user && + role == other.role; + } } diff --git a/packages/shorebird_code_push_protocol/lib/src/models/organization_user.g.dart b/packages/shorebird_code_push_protocol/lib/src/models/organization_user.g.dart deleted file mode 100644 index 620ba27b..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/models/organization_user.g.dart +++ /dev/null @@ -1,36 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ignore_for_file: implicit_dynamic_parameter, require_trailing_commas, cast_nullable_to_non_nullable, lines_longer_than_80_chars - -part of 'organization_user.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -OrganizationUser _$OrganizationUserFromJson(Map json) => - $checkedCreate('OrganizationUser', json, ($checkedConvert) { - final val = OrganizationUser( - user: $checkedConvert( - 'user', - (v) => PublicUser.fromJson(v as Map), - ), - role: $checkedConvert('role', (v) => $enumDecode(_$RoleEnumMap, v)), - ); - return val; - }); - -Map _$OrganizationUserToJson(OrganizationUser instance) => - { - 'user': instance.user.toJson(), - 'role': _$RoleEnumMap[instance.role]!, - }; - -const _$RoleEnumMap = { - Role.owner: 'owner', - Role.admin: 'admin', - Role.appManager: 'appManager', - Role.developer: 'developer', - Role.viewer: 'viewer', - Role.none: 'none', -}; diff --git a/packages/shorebird_code_push_protocol/lib/src/models/patch.dart b/packages/shorebird_code_push_protocol/lib/src/models/patch.dart index e4feba30..fb3ebaa4 100644 --- a/packages/shorebird_code_push_protocol/lib/src/models/patch.dart +++ b/packages/shorebird_code_push_protocol/lib/src/models/patch.dart @@ -1,36 +1,73 @@ -import 'package:equatable/equatable.dart'; -import 'package:json_annotation/json_annotation.dart'; - -part 'patch.g.dart'; +import 'package:meta/meta.dart'; +import 'package:shorebird_code_push_protocol/model_helpers.dart'; /// {@template patch} -/// An over the air update which is applied to a specific release. +/// An over-the-air update which is applied to a specific release. /// All patches have a patch number (auto-incrementing integer) and -/// multiple patches can be published for a given app release version. +/// multiple patches can be published for a given release. /// {@endtemplate} -@JsonSerializable() -class Patch extends Equatable { +@immutable +class Patch { /// {@macro patch} - const Patch({required this.id, required this.number, this.notes}); + const Patch({ + required this.id, + required this.number, + this.notes, + }); - /// Converts a `Map` to a [Patch] - factory Patch.fromJson(Map json) => _$PatchFromJson(json); + /// Converts a `Map` to a [Patch]. + factory Patch.fromJson(Map json) { + return parseFromJson( + 'Patch', + json, + () => Patch( + id: json['id'] as int, + number: json['number'] as int, + notes: json['notes'] as String?, + ), + ); + } - /// Converts a [Patch] to a `Map` - Map toJson() => _$PatchToJson(this); + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static Patch? maybeFromJson(Map? json) { + if (json == null) { + return null; + } + return Patch.fromJson(json); + } /// The unique patch identifier. final int id; - /// The patch number. - /// A larger number equates to a newer patch. + /// The patch number. A larger number equates to a newer patch. final int number; - /// The notes associated with the patch, if any. - /// - /// This value is freeform text with no assumptions about content or format. + /// Freeform notes associated with the patch, if any. final String? notes; + /// Converts a [Patch] to a `Map`. + Map toJson() { + return { + 'id': id, + 'number': number, + 'notes': notes, + }; + } + @override - List get props => [id, number, notes]; + int get hashCode => Object.hashAll([ + id, + number, + notes, + ]); + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is Patch && + id == other.id && + number == other.number && + notes == other.notes; + } } diff --git a/packages/shorebird_code_push_protocol/lib/src/models/patch.g.dart b/packages/shorebird_code_push_protocol/lib/src/models/patch.g.dart deleted file mode 100644 index 9785742d..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/models/patch.g.dart +++ /dev/null @@ -1,25 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ignore_for_file: implicit_dynamic_parameter, require_trailing_commas, cast_nullable_to_non_nullable, lines_longer_than_80_chars - -part of 'patch.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -Patch _$PatchFromJson(Map json) => - $checkedCreate('Patch', json, ($checkedConvert) { - final val = Patch( - id: $checkedConvert('id', (v) => (v as num).toInt()), - number: $checkedConvert('number', (v) => (v as num).toInt()), - notes: $checkedConvert('notes', (v) => v as String?), - ); - return val; - }); - -Map _$PatchToJson(Patch instance) => { - 'id': instance.id, - 'number': instance.number, - 'notes': instance.notes, -}; diff --git a/packages/shorebird_code_push_protocol/lib/src/models/patch_artifact.dart b/packages/shorebird_code_push_protocol/lib/src/models/patch_artifact.dart index 6c5e0356..adb32022 100644 --- a/packages/shorebird_code_push_protocol/lib/src/models/patch_artifact.dart +++ b/packages/shorebird_code_push_protocol/lib/src/models/patch_artifact.dart @@ -1,13 +1,12 @@ -import 'package:json_annotation/json_annotation.dart'; -import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; - -part 'patch_artifact.g.dart'; +import 'package:meta/meta.dart'; +import 'package:shorebird_code_push_protocol/model_helpers.dart'; +import 'package:shorebird_code_push_protocol/src/models/release_platform.dart'; /// {@template patch_artifact} -/// An artifact contains metadata about the contents of a specific patch -/// for a specific platform and architecture. +/// Metadata about the contents of a specific patch for a specific +/// platform and architecture. /// {@endtemplate} -@JsonSerializable() +@immutable class PatchArtifact { /// {@macro patch_artifact} const PatchArtifact({ @@ -20,14 +19,33 @@ class PatchArtifact { required this.createdAt, }); - /// Converts a `Map` to a [PatchArtifact] - factory PatchArtifact.fromJson(Map json) => - _$PatchArtifactFromJson(json); + /// Converts a `Map` to a [PatchArtifact]. + factory PatchArtifact.fromJson(Map json) { + return parseFromJson( + 'PatchArtifact', + json, + () => PatchArtifact( + id: json['id'] as int, + patchId: json['patch_id'] as int, + arch: json['arch'] as String, + platform: ReleasePlatform.fromJson(json['platform'] as String), + hash: json['hash'] as String, + size: json['size'] as int, + createdAt: DateTime.parse(json['created_at'] as String), + ), + ); + } - /// Converts a [PatchArtifact] to a `Map` - Map toJson() => _$PatchArtifactToJson(this); + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static PatchArtifact? maybeFromJson(Map? json) { + if (json == null) { + return null; + } + return PatchArtifact.fromJson(json); + } - /// The ID of the artifact; + /// The ID of the artifact. final int id; /// The ID of the patch. @@ -36,7 +54,7 @@ class PatchArtifact { /// The arch of the artifact. final String arch; - /// The platform of the artifact. + /// A platform to which a Shorebird release can be deployed. final ReleasePlatform platform; /// The hash of the artifact. @@ -47,4 +65,41 @@ class PatchArtifact { /// The date and time the artifact was created. final DateTime createdAt; + + /// Converts a [PatchArtifact] to a `Map`. + Map toJson() { + return { + 'id': id, + 'patch_id': patchId, + 'arch': arch, + 'platform': platform.toJson(), + 'hash': hash, + 'size': size, + 'created_at': createdAt.toIso8601String(), + }; + } + + @override + int get hashCode => Object.hashAll([ + id, + patchId, + arch, + platform, + hash, + size, + createdAt, + ]); + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is PatchArtifact && + id == other.id && + patchId == other.patchId && + arch == other.arch && + platform == other.platform && + hash == other.hash && + size == other.size && + createdAt == other.createdAt; + } } diff --git a/packages/shorebird_code_push_protocol/lib/src/models/patch_artifact.g.dart b/packages/shorebird_code_push_protocol/lib/src/models/patch_artifact.g.dart deleted file mode 100644 index 4b2ff8af..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/models/patch_artifact.g.dart +++ /dev/null @@ -1,53 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ignore_for_file: implicit_dynamic_parameter, require_trailing_commas, cast_nullable_to_non_nullable, lines_longer_than_80_chars - -part of 'patch_artifact.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -PatchArtifact _$PatchArtifactFromJson(Map json) => - $checkedCreate( - 'PatchArtifact', - json, - ($checkedConvert) { - final val = PatchArtifact( - id: $checkedConvert('id', (v) => (v as num).toInt()), - patchId: $checkedConvert('patch_id', (v) => (v as num).toInt()), - arch: $checkedConvert('arch', (v) => v as String), - platform: $checkedConvert( - 'platform', - (v) => $enumDecode(_$ReleasePlatformEnumMap, v), - ), - hash: $checkedConvert('hash', (v) => v as String), - size: $checkedConvert('size', (v) => (v as num).toInt()), - createdAt: $checkedConvert( - 'created_at', - (v) => DateTime.parse(v as String), - ), - ); - return val; - }, - fieldKeyMap: const {'patchId': 'patch_id', 'createdAt': 'created_at'}, - ); - -Map _$PatchArtifactToJson(PatchArtifact instance) => - { - 'id': instance.id, - 'patch_id': instance.patchId, - 'arch': instance.arch, - 'platform': _$ReleasePlatformEnumMap[instance.platform]!, - 'hash': instance.hash, - 'size': instance.size, - 'created_at': instance.createdAt.toIso8601String(), - }; - -const _$ReleasePlatformEnumMap = { - ReleasePlatform.android: 'android', - ReleasePlatform.ios: 'ios', - ReleasePlatform.linux: 'linux', - ReleasePlatform.macos: 'macos', - ReleasePlatform.windows: 'windows', -}; diff --git a/packages/shorebird_code_push_protocol/lib/src/models/patch_check_metadata.dart b/packages/shorebird_code_push_protocol/lib/src/models/patch_check_metadata.dart new file mode 100644 index 00000000..63fdd9a4 --- /dev/null +++ b/packages/shorebird_code_push_protocol/lib/src/models/patch_check_metadata.dart @@ -0,0 +1,80 @@ +import 'package:meta/meta.dart'; +import 'package:shorebird_code_push_protocol/model_helpers.dart'; + +/// {@template patch_check_metadata} +/// Patch metadata representing the contents of a patch for a +/// specific platform and architecture. +/// {@endtemplate} +@immutable +class PatchCheckMetadata { + /// {@macro patch_check_metadata} + const PatchCheckMetadata({ + required this.number, + required this.downloadUrl, + required this.hash, + this.hashSignature, + }); + + /// Converts a `Map` to a [PatchCheckMetadata]. + factory PatchCheckMetadata.fromJson(Map json) { + return parseFromJson( + 'PatchCheckMetadata', + json, + () => PatchCheckMetadata( + number: json['number'] as int, + downloadUrl: json['download_url'] as String, + hash: json['hash'] as String, + hashSignature: json['hash_signature'] as String?, + ), + ); + } + + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static PatchCheckMetadata? maybeFromJson(Map? json) { + if (json == null) { + return null; + } + return PatchCheckMetadata.fromJson(json); + } + + /// The patch number associated with the artifact. + final int number; + + /// The URL of the artifact. + final String downloadUrl; + + /// The hash of the artifact. + final String hash; + + /// The signature of the `hash`. + final String? hashSignature; + + /// Converts a [PatchCheckMetadata] to a `Map`. + Map toJson() { + return { + 'number': number, + 'download_url': downloadUrl, + 'hash': hash, + 'hash_signature': hashSignature, + }; + } + + @override + int get hashCode => Object.hashAll([ + number, + downloadUrl, + hash, + hashSignature, + ]); + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is PatchCheckMetadata && + number == other.number && + downloadUrl == other.downloadUrl && + hash == other.hash && + hashSignature == other.hashSignature; + } +} diff --git a/packages/shorebird_code_push_protocol/lib/src/models/private_user.dart b/packages/shorebird_code_push_protocol/lib/src/models/private_user.dart index 2a66823d..55cac144 100644 --- a/packages/shorebird_code_push_protocol/lib/src/models/private_user.dart +++ b/packages/shorebird_code_push_protocol/lib/src/models/private_user.dart @@ -1,55 +1,49 @@ -import 'package:json_annotation/json_annotation.dart'; import 'package:meta/meta.dart'; -import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:shorebird_code_push_protocol/model_helpers.dart'; -part 'private_user.g.dart'; - -/// {@template user} -/// A fully-detailed user object, possibly including sensitive information. -/// This should only be used when querying the user's own information. For other -/// users, use [PublicUser]. +/// {@template private_user} +/// A fully-detailed user object, possibly including sensitive +/// information. Should only be used when querying the user's own +/// information. /// {@endtemplate} -@JsonSerializable() +@immutable class PrivateUser { - /// {@macro user} + /// {@macro private_user} const PrivateUser({ required this.id, required this.email, required this.jwtIssuer, - this.hasActiveSubscription = false, this.displayName, + this.hasActiveSubscription = false, this.stripeCustomerId, this.patchOverageLimit, }); - /// Converts a `Map` to a [PrivateUser] - factory PrivateUser.fromJson(Map json) => - _$PrivateUserFromJson(json); + /// Converts a `Map` to a [PrivateUser]. + factory PrivateUser.fromJson(Map json) { + return parseFromJson( + 'PrivateUser', + json, + () => PrivateUser( + id: json['id'] as int, + email: json['email'] as String, + displayName: json['display_name'] as String?, + hasActiveSubscription: json['has_active_subscription'] as bool?, + stripeCustomerId: json['stripe_customer_id'] as String?, + jwtIssuer: json['jwt_issuer'] as String, + patchOverageLimit: json['patch_overage_limit'] as int?, + ), + ); + } - // coverage:ignore-start - /// Constructs a user with arbitrary default values for testing. - @visibleForTesting - factory PrivateUser.forTest({ - int id = 42, - String email = 'test@shorebird.dev', - String jwtIssuer = 'https://accounts.google.com', - bool hasActiveSubscription = false, - String? displayName, - String? stripeCustomerId, - int? patchOverageLimit = 0, - }) => PrivateUser( - id: id, - email: email, - jwtIssuer: jwtIssuer, - hasActiveSubscription: hasActiveSubscription, - displayName: displayName, - stripeCustomerId: stripeCustomerId, - patchOverageLimit: patchOverageLimit, - ); - // coverage:ignore-end - - /// Converts a [PrivateUser] to a `Map` - Map toJson() => _$PrivateUserToJson(this); + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static PrivateUser? maybeFromJson(Map? json) { + if (json == null) { + return null; + } + return PrivateUser.fromJson(json); + } /// The unique user identifier. final int id; @@ -61,7 +55,7 @@ class PrivateUser { final String? displayName; /// Whether the user is currently a paying customer. - final bool hasActiveSubscription; + final bool? hasActiveSubscription; /// The user's Stripe customer ID, if they have one. final String? stripeCustomerId; @@ -69,7 +63,44 @@ class PrivateUser { /// The JWT issuer used to create the user. final String jwtIssuer; - /// The maximum number of patch installs that the user has agreed to pay for - /// as part of a pay-as-you-go plan. + /// The maximum number of patch installs the user has agreed to + /// pay for as part of a pay-as-you-go plan. final int? patchOverageLimit; + + /// Converts a [PrivateUser] to a `Map`. + Map toJson() { + return { + 'id': id, + 'email': email, + 'display_name': displayName, + 'has_active_subscription': hasActiveSubscription, + 'stripe_customer_id': stripeCustomerId, + 'jwt_issuer': jwtIssuer, + 'patch_overage_limit': patchOverageLimit, + }; + } + + @override + int get hashCode => Object.hashAll([ + id, + email, + displayName, + hasActiveSubscription, + stripeCustomerId, + jwtIssuer, + patchOverageLimit, + ]); + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is PrivateUser && + id == other.id && + email == other.email && + displayName == other.displayName && + hasActiveSubscription == other.hasActiveSubscription && + stripeCustomerId == other.stripeCustomerId && + jwtIssuer == other.jwtIssuer && + patchOverageLimit == other.patchOverageLimit; + } } diff --git a/packages/shorebird_code_push_protocol/lib/src/models/private_user.g.dart b/packages/shorebird_code_push_protocol/lib/src/models/private_user.g.dart deleted file mode 100644 index 4d42e981..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/models/private_user.g.dart +++ /dev/null @@ -1,53 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ignore_for_file: implicit_dynamic_parameter, require_trailing_commas, cast_nullable_to_non_nullable, lines_longer_than_80_chars - -part of 'private_user.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -PrivateUser _$PrivateUserFromJson(Map json) => $checkedCreate( - 'PrivateUser', - json, - ($checkedConvert) { - final val = PrivateUser( - id: $checkedConvert('id', (v) => (v as num).toInt()), - email: $checkedConvert('email', (v) => v as String), - jwtIssuer: $checkedConvert('jwt_issuer', (v) => v as String), - hasActiveSubscription: $checkedConvert( - 'has_active_subscription', - (v) => v as bool? ?? false, - ), - displayName: $checkedConvert('display_name', (v) => v as String?), - stripeCustomerId: $checkedConvert( - 'stripe_customer_id', - (v) => v as String?, - ), - patchOverageLimit: $checkedConvert( - 'patch_overage_limit', - (v) => (v as num?)?.toInt(), - ), - ); - return val; - }, - fieldKeyMap: const { - 'jwtIssuer': 'jwt_issuer', - 'hasActiveSubscription': 'has_active_subscription', - 'displayName': 'display_name', - 'stripeCustomerId': 'stripe_customer_id', - 'patchOverageLimit': 'patch_overage_limit', - }, -); - -Map _$PrivateUserToJson(PrivateUser instance) => - { - 'id': instance.id, - 'email': instance.email, - 'display_name': instance.displayName, - 'has_active_subscription': instance.hasActiveSubscription, - 'stripe_customer_id': instance.stripeCustomerId, - 'jwt_issuer': instance.jwtIssuer, - 'patch_overage_limit': instance.patchOverageLimit, - }; diff --git a/packages/shorebird_code_push_protocol/lib/src/models/public_user.dart b/packages/shorebird_code_push_protocol/lib/src/models/public_user.dart index 1f9cb32d..8cc14135 100644 --- a/packages/shorebird_code_push_protocol/lib/src/models/public_user.dart +++ b/packages/shorebird_code_push_protocol/lib/src/models/public_user.dart @@ -1,36 +1,39 @@ -import 'package:json_annotation/json_annotation.dart'; -import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:meta/meta.dart'; +import 'package:shorebird_code_push_protocol/model_helpers.dart'; -part 'public_user.g.dart'; - -/// {@template user} -/// A Shorebird user. This is a pared down version of [PrivateUser]. +/// {@template public_user} +/// A Shorebird user with non-sensitive information only. /// {@endtemplate} -@JsonSerializable() +@immutable class PublicUser { - /// {@macro user} - PublicUser({ + /// {@macro public_user} + const PublicUser({ required this.id, required this.email, - required this.displayName, + this.displayName, }); - /// Converts a `Map` to a [PublicUser] - factory PublicUser.fromJson(Map json) => - _$PublicUserFromJson(json); - - /// Constructs a [PublicUser] from a [PrivateUser], removing sensitive - /// information. - factory PublicUser.fromPrivateUser(PrivateUser fullUser) { - return PublicUser( - id: fullUser.id, - email: fullUser.email, - displayName: fullUser.displayName, + /// Converts a `Map` to a [PublicUser]. + factory PublicUser.fromJson(Map json) { + return parseFromJson( + 'PublicUser', + json, + () => PublicUser( + id: json['id'] as int, + email: json['email'] as String, + displayName: json['display_name'] as String?, + ), ); } - /// Converts a [PublicUser] to a JSON map. - Map toJson() => _$PublicUserToJson(this); + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static PublicUser? maybeFromJson(Map? json) { + if (json == null) { + return null; + } + return PublicUser.fromJson(json); + } /// The user's unique identifier. final int id; @@ -40,4 +43,29 @@ class PublicUser { /// The user's name. final String? displayName; + + /// Converts a [PublicUser] to a `Map`. + Map toJson() { + return { + 'id': id, + 'email': email, + 'display_name': displayName, + }; + } + + @override + int get hashCode => Object.hashAll([ + id, + email, + displayName, + ]); + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is PublicUser && + id == other.id && + email == other.email && + displayName == other.displayName; + } } diff --git a/packages/shorebird_code_push_protocol/lib/src/models/public_user.g.dart b/packages/shorebird_code_push_protocol/lib/src/models/public_user.g.dart deleted file mode 100644 index 0d6ed0bc..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/models/public_user.g.dart +++ /dev/null @@ -1,26 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ignore_for_file: implicit_dynamic_parameter, require_trailing_commas, cast_nullable_to_non_nullable, lines_longer_than_80_chars - -part of 'public_user.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -PublicUser _$PublicUserFromJson(Map json) => - $checkedCreate('PublicUser', json, ($checkedConvert) { - final val = PublicUser( - id: $checkedConvert('id', (v) => (v as num).toInt()), - email: $checkedConvert('email', (v) => v as String), - displayName: $checkedConvert('display_name', (v) => v as String?), - ); - return val; - }, fieldKeyMap: const {'displayName': 'display_name'}); - -Map _$PublicUserToJson(PublicUser instance) => - { - 'id': instance.id, - 'email': instance.email, - 'display_name': instance.displayName, - }; diff --git a/packages/shorebird_code_push_protocol/lib/src/models/release.dart b/packages/shorebird_code_push_protocol/lib/src/models/release.dart index 4ac8abcb..82cf4e13 100644 --- a/packages/shorebird_code_push_protocol/lib/src/models/release.dart +++ b/packages/shorebird_code_push_protocol/lib/src/models/release.dart @@ -1,39 +1,64 @@ -import 'package:equatable/equatable.dart'; -import 'package:json_annotation/json_annotation.dart'; import 'package:meta/meta.dart'; -import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; - -part 'release.g.dart'; +import 'package:shorebird_code_push_protocol/model_helpers.dart'; +import 'package:shorebird_code_push_protocol/src/models/release_platform.dart'; +import 'package:shorebird_code_push_protocol/src/models/release_status.dart'; /// {@template release} /// A release build of an application that is distributed to devices. /// A release can have zero or more patches applied to it. /// {@endtemplate} -@JsonSerializable() @immutable -class Release extends Equatable { +class Release { /// {@macro release} const Release({ required this.id, required this.appId, required this.version, required this.flutterRevision, - required this.flutterVersion, - required this.displayName, required this.platformStatuses, required this.createdAt, required this.updatedAt, + this.flutterVersion, + this.displayName, this.notes, }); - /// Converts a `Map` to a [Release] - factory Release.fromJson(Map json) => - _$ReleaseFromJson(json); + /// Converts a `Map` to a [Release]. + factory Release.fromJson(Map json) { + return parseFromJson( + 'Release', + json, + () => Release( + id: json['id'] as int, + appId: json['app_id'] as String, + version: json['version'] as String, + flutterRevision: json['flutter_revision'] as String, + flutterVersion: json['flutter_version'] as String?, + displayName: json['display_name'] as String?, + platformStatuses: (json['platform_statuses'] as Map) + .map( + (key, value) => MapEntry( + ReleasePlatform.fromJson(key), + ReleaseStatus.fromJson(value as String), + ), + ), + createdAt: DateTime.parse(json['created_at'] as String), + updatedAt: DateTime.parse(json['updated_at'] as String), + notes: json['notes'] as String?, + ), + ); + } - /// Converts a [Release] to a `Map` - Map toJson() => _$ReleaseToJson(this); + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static Release? maybeFromJson(Map? json) { + if (json == null) { + return null; + } + return Release.fromJson(json); + } - /// The ID of the release; + /// The ID of the release. final int id; /// The ID of the app. @@ -45,13 +70,11 @@ class Release extends Equatable { /// The Flutter revision used to create the release. final String flutterRevision; - /// The Flutter version used to create the release. - /// - /// This field is optional because it was newly added and - /// older releases do not have this information. + /// The Flutter version used to create the release. Optional + /// because it was added later; older releases do not have it. final String? flutterVersion; - /// The display name for the release + /// The display name for the release. final String? displayName; /// The status of the release for each platform. @@ -63,22 +86,54 @@ class Release extends Equatable { /// The date and time the release was last updated. final DateTime updatedAt; - /// The notes associated with the release, if any. - /// - /// This value is freeform text with no assumptions about content or format. + /// Freeform notes associated with the release, if any. final String? notes; + /// Converts a [Release] to a `Map`. + Map toJson() { + return { + 'id': id, + 'app_id': appId, + 'version': version, + 'flutter_revision': flutterRevision, + 'flutter_version': flutterVersion, + 'display_name': displayName, + 'platform_statuses': platformStatuses.map( + (key, value) => MapEntry(key.toJson(), value.toJson()), + ), + 'created_at': createdAt.toIso8601String(), + 'updated_at': updatedAt.toIso8601String(), + 'notes': notes, + }; + } + @override - List get props => [ + int get hashCode => Object.hashAll([ id, appId, version, flutterRevision, flutterVersion, displayName, - platformStatuses, + mapHash(platformStatuses), createdAt, updatedAt, notes, - ]; + ]); + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is Release && + id == other.id && + appId == other.appId && + version == other.version && + flutterRevision == other.flutterRevision && + flutterVersion == other.flutterVersion && + displayName == other.displayName && + mapsEqual(platformStatuses, other.platformStatuses) && + createdAt == other.createdAt && + updatedAt == other.updatedAt && + notes == other.notes; + } } diff --git a/packages/shorebird_code_push_protocol/lib/src/models/release.g.dart b/packages/shorebird_code_push_protocol/lib/src/models/release.g.dart deleted file mode 100644 index 28260340..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/models/release.g.dart +++ /dev/null @@ -1,81 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ignore_for_file: implicit_dynamic_parameter, require_trailing_commas, cast_nullable_to_non_nullable, lines_longer_than_80_chars - -part of 'release.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -Release _$ReleaseFromJson(Map json) => $checkedCreate( - 'Release', - json, - ($checkedConvert) { - final val = Release( - id: $checkedConvert('id', (v) => (v as num).toInt()), - appId: $checkedConvert('app_id', (v) => v as String), - version: $checkedConvert('version', (v) => v as String), - flutterRevision: $checkedConvert('flutter_revision', (v) => v as String), - flutterVersion: $checkedConvert('flutter_version', (v) => v as String?), - displayName: $checkedConvert('display_name', (v) => v as String?), - platformStatuses: $checkedConvert( - 'platform_statuses', - (v) => (v as Map).map( - (k, e) => MapEntry( - $enumDecode(_$ReleasePlatformEnumMap, k), - $enumDecode(_$ReleaseStatusEnumMap, e), - ), - ), - ), - createdAt: $checkedConvert( - 'created_at', - (v) => DateTime.parse(v as String), - ), - updatedAt: $checkedConvert( - 'updated_at', - (v) => DateTime.parse(v as String), - ), - notes: $checkedConvert('notes', (v) => v as String?), - ); - return val; - }, - fieldKeyMap: const { - 'appId': 'app_id', - 'flutterRevision': 'flutter_revision', - 'flutterVersion': 'flutter_version', - 'displayName': 'display_name', - 'platformStatuses': 'platform_statuses', - 'createdAt': 'created_at', - 'updatedAt': 'updated_at', - }, -); - -Map _$ReleaseToJson(Release instance) => { - 'id': instance.id, - 'app_id': instance.appId, - 'version': instance.version, - 'flutter_revision': instance.flutterRevision, - 'flutter_version': instance.flutterVersion, - 'display_name': instance.displayName, - 'platform_statuses': instance.platformStatuses.map( - (k, e) => - MapEntry(_$ReleasePlatformEnumMap[k]!, _$ReleaseStatusEnumMap[e]!), - ), - 'created_at': instance.createdAt.toIso8601String(), - 'updated_at': instance.updatedAt.toIso8601String(), - 'notes': instance.notes, -}; - -const _$ReleaseStatusEnumMap = { - ReleaseStatus.draft: 'draft', - ReleaseStatus.active: 'active', -}; - -const _$ReleasePlatformEnumMap = { - ReleasePlatform.android: 'android', - ReleasePlatform.ios: 'ios', - ReleasePlatform.linux: 'linux', - ReleasePlatform.macos: 'macos', - ReleasePlatform.windows: 'windows', -}; diff --git a/packages/shorebird_code_push_protocol/lib/src/models/release_artifact.dart b/packages/shorebird_code_push_protocol/lib/src/models/release_artifact.dart index 7bc17e53..af5f0425 100644 --- a/packages/shorebird_code_push_protocol/lib/src/models/release_artifact.dart +++ b/packages/shorebird_code_push_protocol/lib/src/models/release_artifact.dart @@ -1,13 +1,12 @@ -import 'package:json_annotation/json_annotation.dart'; -import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; - -part 'release_artifact.g.dart'; +import 'package:meta/meta.dart'; +import 'package:shorebird_code_push_protocol/model_helpers.dart'; +import 'package:shorebird_code_push_protocol/src/models/release_platform.dart'; /// {@template release_artifact} -/// An artifact contains metadata about the contents of a specific release -/// for a specific platform and architecture. +/// An artifact contains metadata about the contents of a specific +/// release for a specific platform and architecture. /// {@endtemplate} -@JsonSerializable() +@immutable class ReleaseArtifact { /// {@macro release_artifact} const ReleaseArtifact({ @@ -18,18 +17,39 @@ class ReleaseArtifact { required this.hash, required this.size, required this.url, - required this.podfileLockHash, required this.canSideload, + this.podfileLockHash, }); - /// Converts a `Map` to a [ReleaseArtifact] - factory ReleaseArtifact.fromJson(Map json) => - _$ReleaseArtifactFromJson(json); + /// Converts a `Map` to a [ReleaseArtifact]. + factory ReleaseArtifact.fromJson(Map json) { + return parseFromJson( + 'ReleaseArtifact', + json, + () => ReleaseArtifact( + id: json['id'] as int, + releaseId: json['release_id'] as int, + arch: json['arch'] as String, + platform: ReleasePlatform.fromJson(json['platform'] as String), + hash: json['hash'] as String, + size: json['size'] as int, + url: json['url'] as String, + podfileLockHash: json['podfile_lock_hash'] as String?, + canSideload: json['can_sideload'] as bool, + ), + ); + } - /// Converts a [ReleaseArtifact] to a `Map` - Map toJson() => _$ReleaseArtifactToJson(this); + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static ReleaseArtifact? maybeFromJson(Map? json) { + if (json == null) { + return null; + } + return ReleaseArtifact.fromJson(json); + } - /// The ID of the artifact; + /// The ID of the artifact. final int id; /// The ID of the release. @@ -38,7 +58,7 @@ class ReleaseArtifact { /// The arch of the artifact. final String arch; - /// The platform of the artifact. + /// A platform to which a Shorebird release can be deployed. final ReleasePlatform platform; /// The hash of the artifact. @@ -50,13 +70,52 @@ class ReleaseArtifact { /// The url of the artifact. final String url; - /// The hash of the Podfile.lock file used to create the artifact (iOS only). + /// sha256 of the Podfile.lock used to create the artifact (iOS only). final String? podfileLockHash; - /// Whether the artifact can be sideloaded onto a device or not - /// (e.g. non signed iOS artifacts cannot be sideloaded). + /// Whether the artifact can be sideloaded onto a device. final bool canSideload; + /// Converts a [ReleaseArtifact] to a `Map`. + Map toJson() { + return { + 'id': id, + 'release_id': releaseId, + 'arch': arch, + 'platform': platform.toJson(), + 'hash': hash, + 'size': size, + 'url': url, + 'podfile_lock_hash': podfileLockHash, + 'can_sideload': canSideload, + }; + } + @override - String toString() => toJson().toString(); + int get hashCode => Object.hashAll([ + id, + releaseId, + arch, + platform, + hash, + size, + url, + podfileLockHash, + canSideload, + ]); + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is ReleaseArtifact && + id == other.id && + releaseId == other.releaseId && + arch == other.arch && + platform == other.platform && + hash == other.hash && + size == other.size && + url == other.url && + podfileLockHash == other.podfileLockHash && + canSideload == other.canSideload; + } } diff --git a/packages/shorebird_code_push_protocol/lib/src/models/release_artifact.g.dart b/packages/shorebird_code_push_protocol/lib/src/models/release_artifact.g.dart deleted file mode 100644 index 48c1266e..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/models/release_artifact.g.dart +++ /dev/null @@ -1,61 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ignore_for_file: implicit_dynamic_parameter, require_trailing_commas, cast_nullable_to_non_nullable, lines_longer_than_80_chars - -part of 'release_artifact.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -ReleaseArtifact _$ReleaseArtifactFromJson(Map json) => - $checkedCreate( - 'ReleaseArtifact', - json, - ($checkedConvert) { - final val = ReleaseArtifact( - id: $checkedConvert('id', (v) => (v as num).toInt()), - releaseId: $checkedConvert('release_id', (v) => (v as num).toInt()), - arch: $checkedConvert('arch', (v) => v as String), - platform: $checkedConvert( - 'platform', - (v) => $enumDecode(_$ReleasePlatformEnumMap, v), - ), - hash: $checkedConvert('hash', (v) => v as String), - size: $checkedConvert('size', (v) => (v as num).toInt()), - url: $checkedConvert('url', (v) => v as String), - podfileLockHash: $checkedConvert( - 'podfile_lock_hash', - (v) => v as String?, - ), - canSideload: $checkedConvert('can_sideload', (v) => v as bool), - ); - return val; - }, - fieldKeyMap: const { - 'releaseId': 'release_id', - 'podfileLockHash': 'podfile_lock_hash', - 'canSideload': 'can_sideload', - }, - ); - -Map _$ReleaseArtifactToJson(ReleaseArtifact instance) => - { - 'id': instance.id, - 'release_id': instance.releaseId, - 'arch': instance.arch, - 'platform': _$ReleasePlatformEnumMap[instance.platform]!, - 'hash': instance.hash, - 'size': instance.size, - 'url': instance.url, - 'podfile_lock_hash': instance.podfileLockHash, - 'can_sideload': instance.canSideload, - }; - -const _$ReleasePlatformEnumMap = { - ReleasePlatform.android: 'android', - ReleasePlatform.ios: 'ios', - ReleasePlatform.linux: 'linux', - ReleasePlatform.macos: 'macos', - ReleasePlatform.windows: 'windows', -}; diff --git a/packages/shorebird_code_push_protocol/lib/src/models/release_patch.dart b/packages/shorebird_code_push_protocol/lib/src/models/release_patch.dart index 2fd2bbd9..982e7b3c 100644 --- a/packages/shorebird_code_push_protocol/lib/src/models/release_patch.dart +++ b/packages/shorebird_code_push_protocol/lib/src/models/release_patch.dart @@ -1,31 +1,50 @@ -import 'package:equatable/equatable.dart'; -import 'package:json_annotation/json_annotation.dart'; -import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; - -part 'release_patch.g.dart'; +import 'package:meta/meta.dart'; +import 'package:shorebird_code_push_protocol/model_helpers.dart'; +import 'package:shorebird_code_push_protocol/src/models/patch_artifact.dart'; /// {@template release_patch} /// A patch for a given release. /// {@endtemplate} -// TODO(bryanoltman): consolidate this with [Patch] -@JsonSerializable() -class ReleasePatch extends Equatable { +@immutable +class ReleasePatch { /// {@macro release_patch} const ReleasePatch({ required this.id, required this.number, - required this.channel, required this.artifacts, required this.isRolledBack, + this.channel, this.notes, }); - /// Converts a `Map` to a [ReleasePatch] - factory ReleasePatch.fromJson(Map json) => - _$ReleasePatchFromJson(json); + /// Converts a `Map` to a [ReleasePatch]. + factory ReleasePatch.fromJson(Map json) { + return parseFromJson( + 'ReleasePatch', + json, + () => ReleasePatch( + id: json['id'] as int, + number: json['number'] as int, + channel: json['channel'] as String?, + artifacts: (json['artifacts'] as List) + .map( + (e) => PatchArtifact.fromJson(e as Map), + ) + .toList(), + isRolledBack: json['is_rolled_back'] as bool, + notes: json['notes'] as String?, + ), + ); + } - /// Converts a [ReleasePatch] to a `Map` - Json toJson() => _$ReleasePatchToJson(this); + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static ReleasePatch? maybeFromJson(Map? json) { + if (json == null) { + return null; + } + return ReleasePatch.fromJson(json); + } /// The patch id. final int id; @@ -42,18 +61,40 @@ class ReleasePatch extends Equatable { /// Whether the patch has been rolled back. final bool isRolledBack; - /// The notes associated with the patch, if any. - /// - /// This value is freeform text with no assumptions about content or format. + /// Freeform notes associated with the patch, if any. final String? notes; + /// Converts a [ReleasePatch] to a `Map`. + Map toJson() { + return { + 'id': id, + 'number': number, + 'channel': channel, + 'artifacts': artifacts.map((e) => e.toJson()).toList(), + 'is_rolled_back': isRolledBack, + 'notes': notes, + }; + } + @override - List get props => [ + int get hashCode => Object.hashAll([ id, number, channel, - artifacts, + listHash(artifacts), isRolledBack, notes, - ]; + ]); + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is ReleasePatch && + id == other.id && + number == other.number && + channel == other.channel && + listsEqual(artifacts, other.artifacts) && + isRolledBack == other.isRolledBack && + notes == other.notes; + } } diff --git a/packages/shorebird_code_push_protocol/lib/src/models/release_patch.g.dart b/packages/shorebird_code_push_protocol/lib/src/models/release_patch.g.dart deleted file mode 100644 index bb41b9a8..00000000 --- a/packages/shorebird_code_push_protocol/lib/src/models/release_patch.g.dart +++ /dev/null @@ -1,37 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ignore_for_file: implicit_dynamic_parameter, require_trailing_commas, cast_nullable_to_non_nullable, lines_longer_than_80_chars - -part of 'release_patch.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -ReleasePatch _$ReleasePatchFromJson(Map json) => - $checkedCreate('ReleasePatch', json, ($checkedConvert) { - final val = ReleasePatch( - id: $checkedConvert('id', (v) => (v as num).toInt()), - number: $checkedConvert('number', (v) => (v as num).toInt()), - channel: $checkedConvert('channel', (v) => v as String?), - artifacts: $checkedConvert( - 'artifacts', - (v) => (v as List) - .map((e) => PatchArtifact.fromJson(e as Map)) - .toList(), - ), - isRolledBack: $checkedConvert('is_rolled_back', (v) => v as bool), - notes: $checkedConvert('notes', (v) => v as String?), - ); - return val; - }, fieldKeyMap: const {'isRolledBack': 'is_rolled_back'}); - -Map _$ReleasePatchToJson(ReleasePatch instance) => - { - 'id': instance.id, - 'number': instance.number, - 'channel': instance.channel, - 'artifacts': instance.artifacts.map((e) => e.toJson()).toList(), - 'is_rolled_back': instance.isRolledBack, - 'notes': instance.notes, - }; diff --git a/packages/shorebird_code_push_protocol/lib/src/models/release_platform.dart b/packages/shorebird_code_push_protocol/lib/src/models/release_platform.dart index 07b5be1e..5888db4b 100644 --- a/packages/shorebird_code_push_protocol/lib/src/models/release_platform.dart +++ b/packages/shorebird_code_push_protocol/lib/src/models/release_platform.dart @@ -1,29 +1,48 @@ /// A platform to which a Shorebird release can be deployed. enum ReleasePlatform { - /// Android - android('Android'), + /// Android. + android._('android'), - /// iOS - ios('iOS'), + /// iOS. + ios._('ios'), - /// Linux - linux('Linux'), + /// Linux. + linux._('linux'), - /// macOS - macos('macOS'), + /// macOS. + macos._('macos'), - /// Windows - windows('Windows'); + /// Windows. + windows._('windows'); - const ReleasePlatform(this.displayName); + const ReleasePlatform._(this.value); - /// The display name of the platform. - final String displayName; + /// Creates a ReleasePlatform from a json string. + factory ReleasePlatform.fromJson(String json) { + return ReleasePlatform.values.firstWhere( + (value) => value.value == json, + orElse: () => + throw FormatException('Unknown ReleasePlatform value: $json'), + ); + } - /// Whether the platform supports flavors. - bool get supportsFlavors => { - ReleasePlatform.android, - ReleasePlatform.ios, - ReleasePlatform.macos, - }.contains(this); + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static ReleasePlatform? maybeFromJson(String? json) { + if (json == null) { + return null; + } + return ReleasePlatform.fromJson(json); + } + + /// The value of the enum, as a string. This is the exact value + /// from the OpenAPI spec and will be used for network transport. + final String value; + + /// Converts the enum to a json string. + String toJson() => value; + + /// Returns the string value of the enum. + @override + String toString() => value; } diff --git a/packages/shorebird_code_push_protocol/lib/src/models/release_status.dart b/packages/shorebird_code_push_protocol/lib/src/models/release_status.dart index c3223f7c..b7cb78c5 100644 --- a/packages/shorebird_code_push_protocol/lib/src/models/release_status.dart +++ b/packages/shorebird_code_push_protocol/lib/src/models/release_status.dart @@ -1,9 +1,39 @@ /// The status of a release. enum ReleaseStatus { - /// Indicates that the release has been created, but not all platform - /// artifacts have been uploaded. - draft, + /// The release has been created, but not all platform artifacts have been + /// uploaded. + draft._('draft'), - /// Indicates that all platform artifacts have been uploaded for this release. - active, + /// All platform artifacts have been uploaded for this release. + active._('active'); + + const ReleaseStatus._(this.value); + + /// Creates a ReleaseStatus from a json string. + factory ReleaseStatus.fromJson(String json) { + return ReleaseStatus.values.firstWhere( + (value) => value.value == json, + orElse: () => throw FormatException('Unknown ReleaseStatus value: $json'), + ); + } + + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static ReleaseStatus? maybeFromJson(String? json) { + if (json == null) { + return null; + } + return ReleaseStatus.fromJson(json); + } + + /// The value of the enum, as a string. This is the exact value + /// from the OpenAPI spec and will be used for network transport. + final String value; + + /// Converts the enum to a json string. + String toJson() => value; + + /// Returns the string value of the enum. + @override + String toString() => value; } diff --git a/packages/shorebird_code_push_protocol/lib/src/models/role.dart b/packages/shorebird_code_push_protocol/lib/src/models/role.dart index d0381984..7a087140 100644 --- a/packages/shorebird_code_push_protocol/lib/src/models/role.dart +++ b/packages/shorebird_code_push_protocol/lib/src/models/role.dart @@ -1,25 +1,51 @@ -import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; - -/// {@template role} -/// A role that a user can have relative to an [Organization] or [App]. -/// {@endtemplate} +/// A role that a user can have relative to an Organization or App. enum Role { /// User that created the organization. - owner, + owner._('owner'), /// Users who have permissions to manage the organization. - admin, + admin._('admin'), /// Users who have permissions to manage an app. - appManager, + appManager._('appManager'), /// Users who are part of the organization but have limited permissions. - developer, + developer._('developer'), /// Users who have read-only access to the organization. - viewer, + viewer._('viewer'), - /// Users who are not part of the organization but have visibility into it via - /// app collaborator permissions. - none, + /// Users who are not part of the organization but have visibility into it + /// via app collaborator permissions. + none._('none'); + + const Role._(this.value); + + /// Creates a Role from a json string. + factory Role.fromJson(String json) { + return Role.values.firstWhere( + (value) => value.value == json, + orElse: () => throw FormatException('Unknown Role value: $json'), + ); + } + + /// Convenience to create a nullable type from a nullable json object. + /// Useful when parsing optional fields. + static Role? maybeFromJson(String? json) { + if (json == null) { + return null; + } + return Role.fromJson(json); + } + + /// The value of the enum, as a string. This is the exact value + /// from the OpenAPI spec and will be used for network transport. + final String value; + + /// Converts the enum to a json string. + String toJson() => value; + + /// Returns the string value of the enum. + @override + String toString() => value; } diff --git a/packages/shorebird_code_push_protocol/pubspec.yaml b/packages/shorebird_code_push_protocol/pubspec.yaml index b366ab1c..09e2a5e8 100644 --- a/packages/shorebird_code_push_protocol/pubspec.yaml +++ b/packages/shorebird_code_push_protocol/pubspec.yaml @@ -10,13 +10,15 @@ environment: sdk: ">=3.9.0 <4.0.0" dependencies: - decimal: ^3.2.4 - equatable: ^2.0.8 - json_annotation: ^4.11.0 + collection: ^1.19.1 meta: ^1.16.0 dev_dependencies: - build_runner: ^2.13.1 - json_serializable: ^6.13.1 mocktail: ^1.0.5 + # Only used by `tool/gen.dart` to regenerate lib/src/ from the OpenAPI + # spec. Pinned to a git commit until space_gen publishes to pub.dev. + space_gen: + git: + url: https://github.com/eseidel/space_gen.git + ref: 58b4410a9b25bf58e3f76a4ae979cad52d4909cc test: ^1.31.0 diff --git a/packages/shorebird_code_push_protocol/test/generated/messages/create_app/create_app_request_test.dart b/packages/shorebird_code_push_protocol/test/generated/messages/create_app/create_app_request_test.dart new file mode 100644 index 00000000..66ce59b4 --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/messages/create_app/create_app_request_test.dart @@ -0,0 +1,28 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('CreateAppRequest', () { + test('round-trips via maybeFromJson/toJson', () { + const instance = CreateAppRequest( + displayName: 'example', + organizationId: 0, + ); + final parsed = CreateAppRequest.maybeFromJson(instance.toJson())!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(CreateAppRequest.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => CreateAppRequest.maybeFromJson({}), + throwsFormatException, + ); + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/messages/create_app_collaborator/create_app_collaborator_request_test.dart b/packages/shorebird_code_push_protocol/test/generated/messages/create_app_collaborator/create_app_collaborator_request_test.dart new file mode 100644 index 00000000..a771c4b2 --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/messages/create_app_collaborator/create_app_collaborator_request_test.dart @@ -0,0 +1,27 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('CreateAppCollaboratorRequest', () { + test('round-trips via maybeFromJson/toJson', () { + const instance = CreateAppCollaboratorRequest(email: 'user@example.com'); + final parsed = CreateAppCollaboratorRequest.maybeFromJson( + instance.toJson(), + )!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(CreateAppCollaboratorRequest.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => CreateAppCollaboratorRequest.maybeFromJson({}), + throwsFormatException, + ); + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/messages/create_channel/create_channel_request_test.dart b/packages/shorebird_code_push_protocol/test/generated/messages/create_channel/create_channel_request_test.dart new file mode 100644 index 00000000..d8dbff04 --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/messages/create_channel/create_channel_request_test.dart @@ -0,0 +1,25 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('CreateChannelRequest', () { + test('round-trips via maybeFromJson/toJson', () { + const instance = CreateChannelRequest(channel: 'example'); + final parsed = CreateChannelRequest.maybeFromJson(instance.toJson())!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(CreateChannelRequest.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => CreateChannelRequest.maybeFromJson({}), + throwsFormatException, + ); + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/messages/create_patch/create_patch_request_test.dart b/packages/shorebird_code_push_protocol/test/generated/messages/create_patch/create_patch_request_test.dart new file mode 100644 index 00000000..ac2d3d83 --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/messages/create_patch/create_patch_request_test.dart @@ -0,0 +1,28 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('CreatePatchRequest', () { + test('round-trips via maybeFromJson/toJson', () { + const instance = CreatePatchRequest( + releaseId: 0, + metadata: {'key': {}}, + ); + final parsed = CreatePatchRequest.maybeFromJson(instance.toJson())!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(CreatePatchRequest.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => CreatePatchRequest.maybeFromJson({}), + throwsFormatException, + ); + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/messages/create_patch/create_patch_response_test.dart b/packages/shorebird_code_push_protocol/test/generated/messages/create_patch/create_patch_response_test.dart new file mode 100644 index 00000000..0d16cb8d --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/messages/create_patch/create_patch_response_test.dart @@ -0,0 +1,25 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('CreatePatchResponse', () { + test('round-trips via maybeFromJson/toJson', () { + const instance = CreatePatchResponse(id: 0, number: 0); + final parsed = CreatePatchResponse.maybeFromJson(instance.toJson())!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(CreatePatchResponse.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => CreatePatchResponse.maybeFromJson({}), + throwsFormatException, + ); + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/messages/create_patch_artifact/create_patch_artifact_request_test.dart b/packages/shorebird_code_push_protocol/test/generated/messages/create_patch_artifact/create_patch_artifact_request_test.dart new file mode 100644 index 00000000..163d35c9 --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/messages/create_patch_artifact/create_patch_artifact_request_test.dart @@ -0,0 +1,32 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('CreatePatchArtifactRequest', () { + test('round-trips via maybeFromJson/toJson', () { + final instance = CreatePatchArtifactRequest( + arch: 'example', + platform: ReleasePlatform.values.first, + hash: 'example', + size: 0, + ); + final parsed = CreatePatchArtifactRequest.maybeFromJson( + instance.toJson(), + )!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(CreatePatchArtifactRequest.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => CreatePatchArtifactRequest.maybeFromJson({}), + throwsFormatException, + ); + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/messages/create_patch_artifact/create_patch_artifact_response_test.dart b/packages/shorebird_code_push_protocol/test/generated/messages/create_patch_artifact/create_patch_artifact_response_test.dart new file mode 100644 index 00000000..a3b3df61 --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/messages/create_patch_artifact/create_patch_artifact_response_test.dart @@ -0,0 +1,35 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('CreatePatchArtifactResponse', () { + test('round-trips via maybeFromJson/toJson', () { + final instance = CreatePatchArtifactResponse( + id: 0, + patchId: 0, + arch: 'example', + platform: ReleasePlatform.values.first, + hash: 'example', + size: 0, + url: 'example', + ); + final parsed = CreatePatchArtifactResponse.maybeFromJson( + instance.toJson(), + )!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(CreatePatchArtifactResponse.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => CreatePatchArtifactResponse.maybeFromJson({}), + throwsFormatException, + ); + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/messages/create_release/create_release_request_test.dart b/packages/shorebird_code_push_protocol/test/generated/messages/create_release/create_release_request_test.dart new file mode 100644 index 00000000..78407896 --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/messages/create_release/create_release_request_test.dart @@ -0,0 +1,28 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('CreateReleaseRequest', () { + test('round-trips via maybeFromJson/toJson', () { + const instance = CreateReleaseRequest( + version: 'example', + flutterRevision: 'example', + ); + final parsed = CreateReleaseRequest.maybeFromJson(instance.toJson())!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(CreateReleaseRequest.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => CreateReleaseRequest.maybeFromJson({}), + throwsFormatException, + ); + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/messages/create_release/create_release_response_test.dart b/packages/shorebird_code_push_protocol/test/generated/messages/create_release/create_release_response_test.dart new file mode 100644 index 00000000..28c6183e --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/messages/create_release/create_release_response_test.dart @@ -0,0 +1,37 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('CreateReleaseResponse', () { + test('round-trips via maybeFromJson/toJson', () { + final instance = CreateReleaseResponse( + release: Release( + id: 0, + appId: 'example', + version: 'example', + flutterRevision: 'example', + platformStatuses: { + ReleasePlatform.values.first: ReleaseStatus.values.first, + }, + createdAt: DateTime.utc(2024), + updatedAt: DateTime.utc(2024), + ), + ); + final parsed = CreateReleaseResponse.maybeFromJson(instance.toJson())!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(CreateReleaseResponse.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => CreateReleaseResponse.maybeFromJson({}), + throwsFormatException, + ); + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/messages/create_release_artifact/create_release_artifact_request_test.dart b/packages/shorebird_code_push_protocol/test/generated/messages/create_release_artifact/create_release_artifact_request_test.dart new file mode 100644 index 00000000..659681ac --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/messages/create_release_artifact/create_release_artifact_request_test.dart @@ -0,0 +1,33 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('CreateReleaseArtifactRequest', () { + test('round-trips via maybeFromJson/toJson', () { + final instance = CreateReleaseArtifactRequest( + arch: 'example', + platform: ReleasePlatform.values.first, + hash: 'example', + filename: 'example', + size: 0, + ); + final parsed = CreateReleaseArtifactRequest.maybeFromJson( + instance.toJson(), + )!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(CreateReleaseArtifactRequest.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => CreateReleaseArtifactRequest.maybeFromJson({}), + throwsFormatException, + ); + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/messages/create_release_artifact/create_release_artifact_response_test.dart b/packages/shorebird_code_push_protocol/test/generated/messages/create_release_artifact/create_release_artifact_response_test.dart new file mode 100644 index 00000000..9f014a2c --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/messages/create_release_artifact/create_release_artifact_response_test.dart @@ -0,0 +1,35 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('CreateReleaseArtifactResponse', () { + test('round-trips via maybeFromJson/toJson', () { + final instance = CreateReleaseArtifactResponse( + id: 0, + releaseId: 0, + arch: 'example', + platform: ReleasePlatform.values.first, + hash: 'example', + size: 0, + url: 'example', + ); + final parsed = CreateReleaseArtifactResponse.maybeFromJson( + instance.toJson(), + )!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(CreateReleaseArtifactResponse.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => CreateReleaseArtifactResponse.maybeFromJson({}), + throwsFormatException, + ); + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/messages/create_user/create_user_request_test.dart b/packages/shorebird_code_push_protocol/test/generated/messages/create_user/create_user_request_test.dart new file mode 100644 index 00000000..e1c66620 --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/messages/create_user/create_user_request_test.dart @@ -0,0 +1,25 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('CreateUserRequest', () { + test('round-trips via maybeFromJson/toJson', () { + const instance = CreateUserRequest(name: 'example'); + final parsed = CreateUserRequest.maybeFromJson(instance.toJson())!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(CreateUserRequest.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => CreateUserRequest.maybeFromJson({}), + throwsFormatException, + ); + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/messages/error_response_test.dart b/packages/shorebird_code_push_protocol/test/generated/messages/error_response_test.dart new file mode 100644 index 00000000..635cb2c7 --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/messages/error_response_test.dart @@ -0,0 +1,25 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('ErrorResponse', () { + test('round-trips via maybeFromJson/toJson', () { + const instance = ErrorResponse(code: 'example', message: 'example'); + final parsed = ErrorResponse.maybeFromJson(instance.toJson())!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(ErrorResponse.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => ErrorResponse.maybeFromJson({}), + throwsFormatException, + ); + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/messages/get_apps/get_apps_response_test.dart b/packages/shorebird_code_push_protocol/test/generated/messages/get_apps/get_apps_response_test.dart new file mode 100644 index 00000000..f4a9f1e4 --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/messages/get_apps/get_apps_response_test.dart @@ -0,0 +1,34 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('GetAppsResponse', () { + test('round-trips via maybeFromJson/toJson', () { + final instance = GetAppsResponse( + apps: [ + AppMetadata( + appId: 'example', + displayName: 'example', + createdAt: DateTime.utc(2024), + updatedAt: DateTime.utc(2024), + ), + ], + ); + final parsed = GetAppsResponse.maybeFromJson(instance.toJson())!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(GetAppsResponse.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => GetAppsResponse.maybeFromJson({}), + throwsFormatException, + ); + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/messages/get_gcp_download_speed_test_url/get_gcp_download_speed_test_url200_response_test.dart b/packages/shorebird_code_push_protocol/test/generated/messages/get_gcp_download_speed_test_url/get_gcp_download_speed_test_url200_response_test.dart new file mode 100644 index 00000000..542d8b71 --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/messages/get_gcp_download_speed_test_url/get_gcp_download_speed_test_url200_response_test.dart @@ -0,0 +1,31 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('GetGcpDownloadSpeedTestUrl200Response', () { + test('round-trips via maybeFromJson/toJson', () { + const instance = GetGcpDownloadSpeedTestUrl200Response( + downloadUrl: 'example', + ); + final parsed = GetGcpDownloadSpeedTestUrl200Response.maybeFromJson( + instance.toJson(), + )!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(GetGcpDownloadSpeedTestUrl200Response.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => GetGcpDownloadSpeedTestUrl200Response.maybeFromJson( + {}, + ), + throwsFormatException, + ); + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/messages/get_gcp_upload_speed_test_url/get_gcp_upload_speed_test_url200_response_test.dart b/packages/shorebird_code_push_protocol/test/generated/messages/get_gcp_upload_speed_test_url/get_gcp_upload_speed_test_url200_response_test.dart new file mode 100644 index 00000000..ba9496e4 --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/messages/get_gcp_upload_speed_test_url/get_gcp_upload_speed_test_url200_response_test.dart @@ -0,0 +1,31 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('GetGcpUploadSpeedTestUrl200Response', () { + test('round-trips via maybeFromJson/toJson', () { + const instance = GetGcpUploadSpeedTestUrl200Response( + uploadUrl: 'example', + ); + final parsed = GetGcpUploadSpeedTestUrl200Response.maybeFromJson( + instance.toJson(), + )!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(GetGcpUploadSpeedTestUrl200Response.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => GetGcpUploadSpeedTestUrl200Response.maybeFromJson( + {}, + ), + throwsFormatException, + ); + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/messages/get_organization_apps/get_organization_apps_response_test.dart b/packages/shorebird_code_push_protocol/test/generated/messages/get_organization_apps/get_organization_apps_response_test.dart new file mode 100644 index 00000000..73e85c07 --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/messages/get_organization_apps/get_organization_apps_response_test.dart @@ -0,0 +1,36 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('GetOrganizationAppsResponse', () { + test('round-trips via maybeFromJson/toJson', () { + final instance = GetOrganizationAppsResponse( + apps: [ + AppMetadata( + appId: 'example', + displayName: 'example', + createdAt: DateTime.utc(2024), + updatedAt: DateTime.utc(2024), + ), + ], + ); + final parsed = GetOrganizationAppsResponse.maybeFromJson( + instance.toJson(), + )!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(GetOrganizationAppsResponse.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => GetOrganizationAppsResponse.maybeFromJson({}), + throwsFormatException, + ); + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/messages/get_organization_users/get_organization_users_response_test.dart b/packages/shorebird_code_push_protocol/test/generated/messages/get_organization_users/get_organization_users_response_test.dart new file mode 100644 index 00000000..01ba0be1 --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/messages/get_organization_users/get_organization_users_response_test.dart @@ -0,0 +1,34 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('GetOrganizationUsersResponse', () { + test('round-trips via maybeFromJson/toJson', () { + final instance = GetOrganizationUsersResponse( + users: [ + OrganizationUser( + user: const PublicUser(id: 0, email: 'user@example.com'), + role: Role.values.first, + ), + ], + ); + final parsed = GetOrganizationUsersResponse.maybeFromJson( + instance.toJson(), + )!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(GetOrganizationUsersResponse.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => GetOrganizationUsersResponse.maybeFromJson({}), + throwsFormatException, + ); + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/messages/get_organizations_response_test.dart b/packages/shorebird_code_push_protocol/test/generated/messages/get_organizations_response_test.dart new file mode 100644 index 00000000..95fe2c9f --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/messages/get_organizations_response_test.dart @@ -0,0 +1,38 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('GetOrganizationsResponse', () { + test('round-trips via maybeFromJson/toJson', () { + final instance = GetOrganizationsResponse( + organizations: [ + OrganizationMembership( + organization: Organization( + id: 0, + name: 'example', + organizationType: OrganizationType.values.first, + createdAt: DateTime.utc(2024), + updatedAt: DateTime.utc(2024), + ), + role: Role.values.first, + ), + ], + ); + final parsed = GetOrganizationsResponse.maybeFromJson(instance.toJson())!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(GetOrganizationsResponse.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => GetOrganizationsResponse.maybeFromJson({}), + throwsFormatException, + ); + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/messages/get_release/get_release_response_test.dart b/packages/shorebird_code_push_protocol/test/generated/messages/get_release/get_release_response_test.dart new file mode 100644 index 00000000..95d3394e --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/messages/get_release/get_release_response_test.dart @@ -0,0 +1,37 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('GetReleaseResponse', () { + test('round-trips via maybeFromJson/toJson', () { + final instance = GetReleaseResponse( + release: Release( + id: 0, + appId: 'example', + version: 'example', + flutterRevision: 'example', + platformStatuses: { + ReleasePlatform.values.first: ReleaseStatus.values.first, + }, + createdAt: DateTime.utc(2024), + updatedAt: DateTime.utc(2024), + ), + ); + final parsed = GetReleaseResponse.maybeFromJson(instance.toJson())!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(GetReleaseResponse.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => GetReleaseResponse.maybeFromJson({}), + throwsFormatException, + ); + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/messages/get_release_artifacts/get_release_artifacts_response_test.dart b/packages/shorebird_code_push_protocol/test/generated/messages/get_release_artifacts/get_release_artifacts_response_test.dart new file mode 100644 index 00000000..80babad5 --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/messages/get_release_artifacts/get_release_artifacts_response_test.dart @@ -0,0 +1,40 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('GetReleaseArtifactsResponse', () { + test('round-trips via maybeFromJson/toJson', () { + final instance = GetReleaseArtifactsResponse( + artifacts: [ + ReleaseArtifact( + id: 0, + releaseId: 0, + arch: 'example', + platform: ReleasePlatform.values.first, + hash: 'example', + size: 0, + url: 'example', + canSideload: false, + ), + ], + ); + final parsed = GetReleaseArtifactsResponse.maybeFromJson( + instance.toJson(), + )!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(GetReleaseArtifactsResponse.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => GetReleaseArtifactsResponse.maybeFromJson({}), + throwsFormatException, + ); + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/messages/get_release_patches/get_release_patches_response_test.dart b/packages/shorebird_code_push_protocol/test/generated/messages/get_release_patches/get_release_patches_response_test.dart new file mode 100644 index 00000000..778a9ecc --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/messages/get_release_patches/get_release_patches_response_test.dart @@ -0,0 +1,46 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('GetReleasePatchesResponse', () { + test('round-trips via maybeFromJson/toJson', () { + final instance = GetReleasePatchesResponse( + patches: [ + ReleasePatch( + id: 0, + number: 0, + artifacts: [ + PatchArtifact( + id: 0, + patchId: 0, + arch: 'example', + platform: ReleasePlatform.values.first, + hash: 'example', + size: 0, + createdAt: DateTime.utc(2024), + ), + ], + isRolledBack: false, + ), + ], + ); + final parsed = GetReleasePatchesResponse.maybeFromJson( + instance.toJson(), + )!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(GetReleasePatchesResponse.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => GetReleasePatchesResponse.maybeFromJson({}), + throwsFormatException, + ); + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/messages/get_releases/get_releases_response_test.dart b/packages/shorebird_code_push_protocol/test/generated/messages/get_releases/get_releases_response_test.dart new file mode 100644 index 00000000..4527c18a --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/messages/get_releases/get_releases_response_test.dart @@ -0,0 +1,39 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('GetReleasesResponse', () { + test('round-trips via maybeFromJson/toJson', () { + final instance = GetReleasesResponse( + releases: [ + Release( + id: 0, + appId: 'example', + version: 'example', + flutterRevision: 'example', + platformStatuses: { + ReleasePlatform.values.first: ReleaseStatus.values.first, + }, + createdAt: DateTime.utc(2024), + updatedAt: DateTime.utc(2024), + ), + ], + ); + final parsed = GetReleasesResponse.maybeFromJson(instance.toJson())!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(GetReleasesResponse.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => GetReleasesResponse.maybeFromJson({}), + throwsFormatException, + ); + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/messages/patch_check/patch_check_request_test.dart b/packages/shorebird_code_push_protocol/test/generated/messages/patch_check/patch_check_request_test.dart new file mode 100644 index 00000000..4bee2c65 --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/messages/patch_check/patch_check_request_test.dart @@ -0,0 +1,31 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('PatchCheckRequest', () { + test('round-trips via maybeFromJson/toJson', () { + final instance = PatchCheckRequest( + releaseVersion: 'example', + platform: ReleasePlatform.values.first, + arch: 'example', + appId: 'example', + channel: 'example', + ); + final parsed = PatchCheckRequest.maybeFromJson(instance.toJson())!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(PatchCheckRequest.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => PatchCheckRequest.maybeFromJson({}), + throwsFormatException, + ); + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/messages/patch_check/patch_check_response_test.dart b/packages/shorebird_code_push_protocol/test/generated/messages/patch_check/patch_check_response_test.dart new file mode 100644 index 00000000..ce8816a4 --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/messages/patch_check/patch_check_response_test.dart @@ -0,0 +1,25 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('PatchCheckResponse', () { + test('round-trips via maybeFromJson/toJson', () { + const instance = PatchCheckResponse(patchAvailable: false); + final parsed = PatchCheckResponse.maybeFromJson(instance.toJson())!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(PatchCheckResponse.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => PatchCheckResponse.maybeFromJson({}), + throwsFormatException, + ); + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/messages/promote_patch/promote_patch_request_test.dart b/packages/shorebird_code_push_protocol/test/generated/messages/promote_patch/promote_patch_request_test.dart new file mode 100644 index 00000000..3317b752 --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/messages/promote_patch/promote_patch_request_test.dart @@ -0,0 +1,25 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('PromotePatchRequest', () { + test('round-trips via maybeFromJson/toJson', () { + const instance = PromotePatchRequest(patchId: 0, channelId: 0); + final parsed = PromotePatchRequest.maybeFromJson(instance.toJson())!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(PromotePatchRequest.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => PromotePatchRequest.maybeFromJson({}), + throwsFormatException, + ); + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/messages/update_app_collaborator/update_app_collaborator_request_test.dart b/packages/shorebird_code_push_protocol/test/generated/messages/update_app_collaborator/update_app_collaborator_request_test.dart new file mode 100644 index 00000000..bfe95180 --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/messages/update_app_collaborator/update_app_collaborator_request_test.dart @@ -0,0 +1,29 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('UpdateAppCollaboratorRequest', () { + test('round-trips via maybeFromJson/toJson', () { + final instance = UpdateAppCollaboratorRequest( + role: AppCollaboratorRole.values.first, + ); + final parsed = UpdateAppCollaboratorRequest.maybeFromJson( + instance.toJson(), + )!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(UpdateAppCollaboratorRequest.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => UpdateAppCollaboratorRequest.maybeFromJson({}), + throwsFormatException, + ); + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/messages/update_patch/update_patch_request_test.dart b/packages/shorebird_code_push_protocol/test/generated/messages/update_patch/update_patch_request_test.dart new file mode 100644 index 00000000..738f47eb --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/messages/update_patch/update_patch_request_test.dart @@ -0,0 +1,18 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('UpdatePatchRequest', () { + test('round-trips via maybeFromJson/toJson', () { + const instance = UpdatePatchRequest(); + final parsed = UpdatePatchRequest.maybeFromJson(instance.toJson())!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(UpdatePatchRequest.maybeFromJson(null), isNull); + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/messages/update_release/update_release_request_test.dart b/packages/shorebird_code_push_protocol/test/generated/messages/update_release/update_release_request_test.dart new file mode 100644 index 00000000..6c844cb9 --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/messages/update_release/update_release_request_test.dart @@ -0,0 +1,18 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('UpdateReleaseRequest', () { + test('round-trips via maybeFromJson/toJson', () { + const instance = UpdateReleaseRequest(); + final parsed = UpdateReleaseRequest.maybeFromJson(instance.toJson())!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(UpdateReleaseRequest.maybeFromJson(null), isNull); + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/models/app_collaborator_role_test.dart b/packages/shorebird_code_push_protocol/test/generated/models/app_collaborator_role_test.dart new file mode 100644 index 00000000..c71dfae6 --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/models/app_collaborator_role_test.dart @@ -0,0 +1,37 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('AppCollaboratorRole', () { + test('round-trips via maybeFromJson/toJson', () { + final instance = AppCollaboratorRole.values.first; + final parsed = AppCollaboratorRole.maybeFromJson(instance.toJson())!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(AppCollaboratorRole.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => AppCollaboratorRole.maybeFromJson('__invalid_enum_value__'), + throwsFormatException, + ); + }); + + test('toString matches toJson for every value', () { + for (final value in AppCollaboratorRole.values) { + expect(value.toString(), equals(value.toJson())); + } + }); + + test('fromJson round-trips every value', () { + for (final value in AppCollaboratorRole.values) { + expect(AppCollaboratorRole.fromJson(value.toJson()), equals(value)); + } + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/models/app_metadata_test.dart b/packages/shorebird_code_push_protocol/test/generated/models/app_metadata_test.dart new file mode 100644 index 00000000..25b0d1cf --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/models/app_metadata_test.dart @@ -0,0 +1,30 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('AppMetadata', () { + test('round-trips via maybeFromJson/toJson', () { + final instance = AppMetadata( + appId: 'example', + displayName: 'example', + createdAt: DateTime.utc(2024), + updatedAt: DateTime.utc(2024), + ); + final parsed = AppMetadata.maybeFromJson(instance.toJson())!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(AppMetadata.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => AppMetadata.maybeFromJson({}), + throwsFormatException, + ); + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/models/app_test.dart b/packages/shorebird_code_push_protocol/test/generated/models/app_test.dart new file mode 100644 index 00000000..ddd0fc65 --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/models/app_test.dart @@ -0,0 +1,25 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('App', () { + test('round-trips via maybeFromJson/toJson', () { + const instance = App(id: 'example', displayName: 'example'); + final parsed = App.maybeFromJson(instance.toJson())!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(App.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => App.maybeFromJson({}), + throwsFormatException, + ); + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/models/channel_test.dart b/packages/shorebird_code_push_protocol/test/generated/models/channel_test.dart new file mode 100644 index 00000000..9eb154d0 --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/models/channel_test.dart @@ -0,0 +1,25 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('Channel', () { + test('round-trips via maybeFromJson/toJson', () { + const instance = Channel(id: 0, appId: 'example', name: 'example'); + final parsed = Channel.maybeFromJson(instance.toJson())!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(Channel.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => Channel.maybeFromJson({}), + throwsFormatException, + ); + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/models/organization_membership_test.dart b/packages/shorebird_code_push_protocol/test/generated/models/organization_membership_test.dart new file mode 100644 index 00000000..00e1c676 --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/models/organization_membership_test.dart @@ -0,0 +1,34 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('OrganizationMembership', () { + test('round-trips via maybeFromJson/toJson', () { + final instance = OrganizationMembership( + organization: Organization( + id: 0, + name: 'example', + organizationType: OrganizationType.values.first, + createdAt: DateTime.utc(2024), + updatedAt: DateTime.utc(2024), + ), + role: Role.values.first, + ); + final parsed = OrganizationMembership.maybeFromJson(instance.toJson())!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(OrganizationMembership.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => OrganizationMembership.maybeFromJson({}), + throwsFormatException, + ); + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/models/organization_test.dart b/packages/shorebird_code_push_protocol/test/generated/models/organization_test.dart new file mode 100644 index 00000000..80f5edc1 --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/models/organization_test.dart @@ -0,0 +1,31 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('Organization', () { + test('round-trips via maybeFromJson/toJson', () { + final instance = Organization( + id: 0, + name: 'example', + organizationType: OrganizationType.values.first, + createdAt: DateTime.utc(2024), + updatedAt: DateTime.utc(2024), + ); + final parsed = Organization.maybeFromJson(instance.toJson())!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(Organization.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => Organization.maybeFromJson({}), + throwsFormatException, + ); + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/models/organization_type_test.dart b/packages/shorebird_code_push_protocol/test/generated/models/organization_type_test.dart new file mode 100644 index 00000000..5a5aa5e5 --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/models/organization_type_test.dart @@ -0,0 +1,37 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('OrganizationType', () { + test('round-trips via maybeFromJson/toJson', () { + final instance = OrganizationType.values.first; + final parsed = OrganizationType.maybeFromJson(instance.toJson())!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(OrganizationType.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => OrganizationType.maybeFromJson('__invalid_enum_value__'), + throwsFormatException, + ); + }); + + test('toString matches toJson for every value', () { + for (final value in OrganizationType.values) { + expect(value.toString(), equals(value.toJson())); + } + }); + + test('fromJson round-trips every value', () { + for (final value in OrganizationType.values) { + expect(OrganizationType.fromJson(value.toJson()), equals(value)); + } + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/models/organization_user_test.dart b/packages/shorebird_code_push_protocol/test/generated/models/organization_user_test.dart new file mode 100644 index 00000000..8254ca29 --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/models/organization_user_test.dart @@ -0,0 +1,28 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('OrganizationUser', () { + test('round-trips via maybeFromJson/toJson', () { + final instance = OrganizationUser( + user: const PublicUser(id: 0, email: 'user@example.com'), + role: Role.values.first, + ); + final parsed = OrganizationUser.maybeFromJson(instance.toJson())!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(OrganizationUser.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => OrganizationUser.maybeFromJson({}), + throwsFormatException, + ); + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/models/patch_artifact_test.dart b/packages/shorebird_code_push_protocol/test/generated/models/patch_artifact_test.dart new file mode 100644 index 00000000..ff25f2b9 --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/models/patch_artifact_test.dart @@ -0,0 +1,33 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('PatchArtifact', () { + test('round-trips via maybeFromJson/toJson', () { + final instance = PatchArtifact( + id: 0, + patchId: 0, + arch: 'example', + platform: ReleasePlatform.values.first, + hash: 'example', + size: 0, + createdAt: DateTime.utc(2024), + ); + final parsed = PatchArtifact.maybeFromJson(instance.toJson())!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(PatchArtifact.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => PatchArtifact.maybeFromJson({}), + throwsFormatException, + ); + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/models/patch_check_metadata_test.dart b/packages/shorebird_code_push_protocol/test/generated/models/patch_check_metadata_test.dart new file mode 100644 index 00000000..4c50b0ec --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/models/patch_check_metadata_test.dart @@ -0,0 +1,29 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('PatchCheckMetadata', () { + test('round-trips via maybeFromJson/toJson', () { + const instance = PatchCheckMetadata( + number: 0, + downloadUrl: 'example', + hash: 'example', + ); + final parsed = PatchCheckMetadata.maybeFromJson(instance.toJson())!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(PatchCheckMetadata.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => PatchCheckMetadata.maybeFromJson({}), + throwsFormatException, + ); + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/models/patch_test.dart b/packages/shorebird_code_push_protocol/test/generated/models/patch_test.dart new file mode 100644 index 00000000..9731b5a2 --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/models/patch_test.dart @@ -0,0 +1,18 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('Patch', () { + test('round-trips via maybeFromJson/toJson', () { + const instance = Patch(id: 0, number: 0); + final parsed = Patch.maybeFromJson(instance.toJson())!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(Patch.maybeFromJson(null), isNull); + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/models/private_user_test.dart b/packages/shorebird_code_push_protocol/test/generated/models/private_user_test.dart new file mode 100644 index 00000000..22c89f02 --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/models/private_user_test.dart @@ -0,0 +1,29 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('PrivateUser', () { + test('round-trips via maybeFromJson/toJson', () { + const instance = PrivateUser( + id: 0, + email: 'user@example.com', + jwtIssuer: 'example', + ); + final parsed = PrivateUser.maybeFromJson(instance.toJson())!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(PrivateUser.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => PrivateUser.maybeFromJson({}), + throwsFormatException, + ); + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/models/public_user_test.dart b/packages/shorebird_code_push_protocol/test/generated/models/public_user_test.dart new file mode 100644 index 00000000..554b1a20 --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/models/public_user_test.dart @@ -0,0 +1,25 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('PublicUser', () { + test('round-trips via maybeFromJson/toJson', () { + const instance = PublicUser(id: 0, email: 'user@example.com'); + final parsed = PublicUser.maybeFromJson(instance.toJson())!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(PublicUser.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => PublicUser.maybeFromJson({}), + throwsFormatException, + ); + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/models/release_artifact_test.dart b/packages/shorebird_code_push_protocol/test/generated/models/release_artifact_test.dart new file mode 100644 index 00000000..8f4aad29 --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/models/release_artifact_test.dart @@ -0,0 +1,34 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('ReleaseArtifact', () { + test('round-trips via maybeFromJson/toJson', () { + final instance = ReleaseArtifact( + id: 0, + releaseId: 0, + arch: 'example', + platform: ReleasePlatform.values.first, + hash: 'example', + size: 0, + url: 'example', + canSideload: false, + ); + final parsed = ReleaseArtifact.maybeFromJson(instance.toJson())!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(ReleaseArtifact.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => ReleaseArtifact.maybeFromJson({}), + throwsFormatException, + ); + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/models/release_patch_test.dart b/packages/shorebird_code_push_protocol/test/generated/models/release_patch_test.dart new file mode 100644 index 00000000..237819ba --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/models/release_patch_test.dart @@ -0,0 +1,40 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('ReleasePatch', () { + test('round-trips via maybeFromJson/toJson', () { + final instance = ReleasePatch( + id: 0, + number: 0, + artifacts: [ + PatchArtifact( + id: 0, + patchId: 0, + arch: 'example', + platform: ReleasePlatform.values.first, + hash: 'example', + size: 0, + createdAt: DateTime.utc(2024), + ), + ], + isRolledBack: false, + ); + final parsed = ReleasePatch.maybeFromJson(instance.toJson())!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(ReleasePatch.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => ReleasePatch.maybeFromJson({}), + throwsFormatException, + ); + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/models/release_platform_test.dart b/packages/shorebird_code_push_protocol/test/generated/models/release_platform_test.dart new file mode 100644 index 00000000..2402e2ed --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/models/release_platform_test.dart @@ -0,0 +1,37 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('ReleasePlatform', () { + test('round-trips via maybeFromJson/toJson', () { + final instance = ReleasePlatform.values.first; + final parsed = ReleasePlatform.maybeFromJson(instance.toJson())!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(ReleasePlatform.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => ReleasePlatform.maybeFromJson('__invalid_enum_value__'), + throwsFormatException, + ); + }); + + test('toString matches toJson for every value', () { + for (final value in ReleasePlatform.values) { + expect(value.toString(), equals(value.toJson())); + } + }); + + test('fromJson round-trips every value', () { + for (final value in ReleasePlatform.values) { + expect(ReleasePlatform.fromJson(value.toJson()), equals(value)); + } + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/models/release_status_test.dart b/packages/shorebird_code_push_protocol/test/generated/models/release_status_test.dart new file mode 100644 index 00000000..f34d74e2 --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/models/release_status_test.dart @@ -0,0 +1,37 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('ReleaseStatus', () { + test('round-trips via maybeFromJson/toJson', () { + final instance = ReleaseStatus.values.first; + final parsed = ReleaseStatus.maybeFromJson(instance.toJson())!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(ReleaseStatus.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => ReleaseStatus.maybeFromJson('__invalid_enum_value__'), + throwsFormatException, + ); + }); + + test('toString matches toJson for every value', () { + for (final value in ReleaseStatus.values) { + expect(value.toString(), equals(value.toJson())); + } + }); + + test('fromJson round-trips every value', () { + for (final value in ReleaseStatus.values) { + expect(ReleaseStatus.fromJson(value.toJson()), equals(value)); + } + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/models/release_test.dart b/packages/shorebird_code_push_protocol/test/generated/models/release_test.dart new file mode 100644 index 00000000..16a8f9f0 --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/models/release_test.dart @@ -0,0 +1,35 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('Release', () { + test('round-trips via maybeFromJson/toJson', () { + final instance = Release( + id: 0, + appId: 'example', + version: 'example', + flutterRevision: 'example', + platformStatuses: { + ReleasePlatform.values.first: ReleaseStatus.values.first, + }, + createdAt: DateTime.utc(2024), + updatedAt: DateTime.utc(2024), + ); + final parsed = Release.maybeFromJson(instance.toJson())!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(Release.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => Release.maybeFromJson({}), + throwsFormatException, + ); + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/generated/models/role_test.dart b/packages/shorebird_code_push_protocol/test/generated/models/role_test.dart new file mode 100644 index 00000000..1ce0faf4 --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/generated/models/role_test.dart @@ -0,0 +1,37 @@ +// GENERATED — do not hand-edit. +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group('Role', () { + test('round-trips via maybeFromJson/toJson', () { + final instance = Role.values.first; + final parsed = Role.maybeFromJson(instance.toJson())!; + expect(parsed, equals(instance)); + expect(parsed.hashCode, equals(instance.hashCode)); + }); + + test('maybeFromJson returns null on null input', () { + expect(Role.maybeFromJson(null), isNull); + }); + + test('maybeFromJson throws FormatException on invalid input', () { + expect( + () => Role.maybeFromJson('__invalid_enum_value__'), + throwsFormatException, + ); + }); + + test('toString matches toJson for every value', () { + for (final value in Role.values) { + expect(value.toString(), equals(value.toJson())); + } + }); + + test('fromJson round-trips every value', () { + for (final value in Role.values) { + expect(Role.fromJson(value.toJson()), equals(value)); + } + }); + }); +} diff --git a/packages/shorebird_code_push_protocol/test/src/messages/create_patch/create_patch_response_test.dart b/packages/shorebird_code_push_protocol/test/src/messages/create_patch/create_patch_response_test.dart deleted file mode 100644 index 3ea5cbe4..00000000 --- a/packages/shorebird_code_push_protocol/test/src/messages/create_patch/create_patch_response_test.dart +++ /dev/null @@ -1,14 +0,0 @@ -import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; -import 'package:test/test.dart'; - -void main() { - group(CreatePatchResponse, () { - test('can be (de)serialized', () { - const response = CreatePatchResponse(id: 42, number: 1); - expect( - CreatePatchResponse.fromJson(response.toJson()).toJson(), - equals(response.toJson()), - ); - }); - }); -} diff --git a/packages/shorebird_code_push_protocol/test/src/messages/create_release_artifact/create_release_artifact_request_test.dart b/packages/shorebird_code_push_protocol/test/src/messages/create_release_artifact/create_release_artifact_request_test.dart index 29d514d5..de23a195 100644 --- a/packages/shorebird_code_push_protocol/test/src/messages/create_release_artifact/create_release_artifact_request_test.dart +++ b/packages/shorebird_code_push_protocol/test/src/messages/create_release_artifact/create_release_artifact_request_test.dart @@ -11,7 +11,6 @@ void main() { size: 9876, canSideload: true, filename: 'test.apk', - podfileLockHash: null, ); expect( CreateReleaseArtifactRequest.fromJson(request.toJson()).toJson(), diff --git a/packages/shorebird_code_push_protocol/test/src/messages/get_organization_users/get_organization_users_response_test.dart b/packages/shorebird_code_push_protocol/test/src/messages/get_organization_users/get_organization_users_response_test.dart index 17620363..67232e2b 100644 --- a/packages/shorebird_code_push_protocol/test/src/messages/get_organization_users/get_organization_users_response_test.dart +++ b/packages/shorebird_code_push_protocol/test/src/messages/get_organization_users/get_organization_users_response_test.dart @@ -7,7 +7,7 @@ void main() { final getOrganizationUsersRequest = GetOrganizationUsersResponse( users: [ OrganizationUser( - user: PublicUser.fromPrivateUser(PrivateUser.forTest()), + user: publicUserFromPrivateUser(privateUserForTest()), role: Role.owner, ), ], diff --git a/packages/shorebird_code_push_protocol/test/src/messages/get_organizations/get_organizations_response_test.dart b/packages/shorebird_code_push_protocol/test/src/messages/get_organizations/get_organizations_response_test.dart index 9d54c81d..c7af1c45 100644 --- a/packages/shorebird_code_push_protocol/test/src/messages/get_organizations/get_organizations_response_test.dart +++ b/packages/shorebird_code_push_protocol/test/src/messages/get_organizations/get_organizations_response_test.dart @@ -7,7 +7,7 @@ void main() { final getOrganizationsResponse = GetOrganizationsResponse( organizations: [ OrganizationMembership( - organization: Organization.forTest(), + organization: organizationForTest(), role: Role.developer, ), ], diff --git a/packages/shorebird_code_push_protocol/test/src/messages/get_release_patches/get_release_patches_response_test.dart b/packages/shorebird_code_push_protocol/test/src/messages/get_release_patches/get_release_patches_response_test.dart index 292af611..05ad944d 100644 --- a/packages/shorebird_code_push_protocol/test/src/messages/get_release_patches/get_release_patches_response_test.dart +++ b/packages/shorebird_code_push_protocol/test/src/messages/get_release_patches/get_release_patches_response_test.dart @@ -35,7 +35,6 @@ void main() { ReleasePatch( id: 43, number: 2, - channel: null, isRolledBack: false, artifacts: [ PatchArtifact( diff --git a/packages/shorebird_code_push_protocol/test/src/messages/patch_check/patch_check_response_test.dart b/packages/shorebird_code_push_protocol/test/src/messages/patch_check/patch_check_response_test.dart index 56f47d51..e85fa83b 100644 --- a/packages/shorebird_code_push_protocol/test/src/messages/patch_check/patch_check_response_test.dart +++ b/packages/shorebird_code_push_protocol/test/src/messages/patch_check/patch_check_response_test.dart @@ -6,11 +6,9 @@ void main() { test('uses value equality', () { expect( // Ignoring for value quality testing. - // ignore: prefer_const_constructors - PatchCheckResponse(patchAvailable: true), + const PatchCheckResponse(patchAvailable: true), // Ignoring for value quality testing. - // ignore: prefer_const_constructors - equals(PatchCheckResponse(patchAvailable: true)), + equals(const PatchCheckResponse(patchAvailable: true)), ); }); @@ -34,21 +32,17 @@ void main() { test('PatchCheckMetadata uses value equality', () { expect( // Ignoring for value quality testing. - // ignore: prefer_const_constructors - PatchCheckMetadata( + const PatchCheckMetadata( number: 1, downloadUrl: 'https://download.com', hash: '1234', - hashSignature: null, ), equals( // Ignoring for value quality testing. - // ignore: prefer_const_constructors - PatchCheckMetadata( + const PatchCheckMetadata( number: 1, downloadUrl: 'https://download.com', hash: '1234', - hashSignature: null, ), ), ); @@ -59,7 +53,6 @@ void main() { number: 1, downloadUrl: 'https://download.com', hash: '1234', - hashSignature: null, ); expect( PatchCheckMetadata.fromJson(metadata.toJson()).toJson(), @@ -74,15 +67,18 @@ void main() { number: 1, downloadUrl: 'https://download.com', hash: '1234', - hashSignature: null, ), ); + // Generated code always emits nullable fields as `null` rather than + // dropping them. Wire-equivalent for JSON consumers that treat + // absent == null. expect(response.toJson(), { 'patch_available': true, 'patch': { 'number': 1, 'download_url': 'https://download.com', 'hash': '1234', + 'hash_signature': null, }, 'rolled_back_patch_numbers': null, }); @@ -124,6 +120,14 @@ void main() { 'rolled_back_patch_numbers': [1, 2, 3], }); }); + + test('parses the rolled back patch numbers from json', () { + final response = PatchCheckResponse.fromJson(const { + 'patch_available': true, + 'rolled_back_patch_numbers': [1, 2, 3], + }); + expect(response.rolledBackPatchNumbers, equals([1, 2, 3])); + }); }); }); } diff --git a/packages/shorebird_code_push_protocol/test/src/models/app_metadata_test.dart b/packages/shorebird_code_push_protocol/test/src/models/app_metadata_test.dart index b922da8e..333d75a0 100644 --- a/packages/shorebird_code_push_protocol/test/src/models/app_metadata_test.dart +++ b/packages/shorebird_code_push_protocol/test/src/models/app_metadata_test.dart @@ -1,4 +1,3 @@ -import 'package:equatable/equatable.dart'; import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; import 'package:test/test.dart'; @@ -19,7 +18,7 @@ void main() { ); }); - group(Equatable, () { + group('equality', () { test('should return true if all properties are equal', () { final appMetadata1 = AppMetadata( appId: '30370f27-dbf1-4673-8b20-fb096e38dffa', diff --git a/packages/shorebird_code_push_protocol/test/src/models/organization_membership_test.dart b/packages/shorebird_code_push_protocol/test/src/models/organization_membership_test.dart index 773ebebb..ee1216cb 100644 --- a/packages/shorebird_code_push_protocol/test/src/models/organization_membership_test.dart +++ b/packages/shorebird_code_push_protocol/test/src/models/organization_membership_test.dart @@ -5,7 +5,7 @@ void main() { group(OrganizationMembership, () { test('can be (de)serialized', () { final membership = OrganizationMembership( - organization: Organization.forTest(), + organization: organizationForTest(), role: Role.developer, ); expect( @@ -20,14 +20,14 @@ void main() { group('when two instances are equal', () { test('returns true', () { final membership = OrganizationMembership( - organization: Organization.forTest( + organization: organizationForTest( createdAt: date, updatedAt: date, ), role: Role.developer, ); final otherMembership = OrganizationMembership( - organization: Organization.forTest( + organization: organizationForTest( createdAt: date, updatedAt: date, ), @@ -40,14 +40,14 @@ void main() { group('when two instances are not equal', () { test('returns false', () { final membership = OrganizationMembership( - organization: Organization.forTest( + organization: organizationForTest( createdAt: date, updatedAt: date, ), role: Role.developer, ); final otherMembership = OrganizationMembership( - organization: Organization.forTest( + organization: organizationForTest( createdAt: date, updatedAt: date, ), diff --git a/packages/shorebird_code_push_protocol/test/src/models/organization_user_test.dart b/packages/shorebird_code_push_protocol/test/src/models/organization_user_test.dart index dd135c6c..7f148703 100644 --- a/packages/shorebird_code_push_protocol/test/src/models/organization_user_test.dart +++ b/packages/shorebird_code_push_protocol/test/src/models/organization_user_test.dart @@ -5,7 +5,7 @@ void main() { group(OrganizationUser, () { test('can be (de)serialized', () { final organizationUser = OrganizationUser( - user: PublicUser.fromPrivateUser(PrivateUser.forTest()), + user: publicUserFromPrivateUser(privateUserForTest()), role: Role.developer, ); expect( diff --git a/packages/shorebird_code_push_protocol/test/src/models/release_artifact_test.dart b/packages/shorebird_code_push_protocol/test/src/models/release_artifact_test.dart index 7bcb55ef..6975d7cc 100644 --- a/packages/shorebird_code_push_protocol/test/src/models/release_artifact_test.dart +++ b/packages/shorebird_code_push_protocol/test/src/models/release_artifact_test.dart @@ -21,23 +21,9 @@ void main() { ); }); - test('toString prints a json representation of the object', () { - const artifact = ReleaseArtifact( - id: 1, - releaseId: 1, - arch: 'aarch64', - platform: ReleasePlatform.android, - url: 'https://example.com', - size: 42, - hash: 'sha256:1234567890', - podfileLockHash: 'podfile-lock-hash', - canSideload: true, - ); - final artifactString = artifact.toString(); - expect( - artifactString, - '{id: 1, release_id: 1, arch: aarch64, platform: android, hash: sha256:1234567890, size: 42, url: https://example.com, podfile_lock_hash: podfile-lock-hash, can_sideload: true}', - ); - }); + // Intentionally removed: the handwritten ReleaseArtifact overrode + // toString to return the JSON-encoded body. The generated class does + // not, which matches Dart defaults for data classes. Callers that + // want a JSON string should call `artifact.toJson().toString()`. }); } diff --git a/packages/shorebird_code_push_protocol/test/src/models/release_patch_test.dart b/packages/shorebird_code_push_protocol/test/src/models/release_patch_test.dart index d3825e57..b04d3b1f 100644 --- a/packages/shorebird_code_push_protocol/test/src/models/release_patch_test.dart +++ b/packages/shorebird_code_push_protocol/test/src/models/release_patch_test.dart @@ -6,23 +6,21 @@ void main() { test('is equatable', () { expect( // Ignoring const constructor for equality comparison. - // ignore: prefer_const_constructors - ReleasePatch( + const ReleasePatch( id: 0, number: 1, channel: 'channel', isRolledBack: false, - artifacts: const [], + artifacts: [], ), equals( // Ignoring const constructor for equality comparison. - // ignore: prefer_const_constructors - ReleasePatch( + const ReleasePatch( id: 0, number: 1, channel: 'channel', isRolledBack: false, - artifacts: const [], + artifacts: [], ), ), ); diff --git a/packages/shorebird_code_push_protocol/test/src/models/release_platform_test.dart b/packages/shorebird_code_push_protocol/test/src/models/release_platform_test.dart index 605cbfc9..47def272 100644 --- a/packages/shorebird_code_push_protocol/test/src/models/release_platform_test.dart +++ b/packages/shorebird_code_push_protocol/test/src/models/release_platform_test.dart @@ -1,4 +1,4 @@ -import 'package:shorebird_code_push_protocol/src/models/models.dart'; +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; import 'package:test/test.dart'; void main() { @@ -22,5 +22,27 @@ void main() { test('windows does not support flavors', () { expect(ReleasePlatform.windows.supportsFlavors, isFalse); }); + + group('displayName', () { + test('android', () { + expect(ReleasePlatform.android.displayName, 'Android'); + }); + + test('ios', () { + expect(ReleasePlatform.ios.displayName, 'iOS'); + }); + + test('linux', () { + expect(ReleasePlatform.linux.displayName, 'Linux'); + }); + + test('macos', () { + expect(ReleasePlatform.macos.displayName, 'macOS'); + }); + + test('windows', () { + expect(ReleasePlatform.windows.displayName, 'Windows'); + }); + }); }); } diff --git a/packages/shorebird_code_push_protocol/tool/gen.dart b/packages/shorebird_code_push_protocol/tool/gen.dart new file mode 100644 index 00000000..e276ec04 --- /dev/null +++ b/packages/shorebird_code_push_protocol/tool/gen.dart @@ -0,0 +1,114 @@ +// Regeneration entrypoint for the shorebird_code_push_protocol package. +// +// Plugs a Shorebird-specific [FileRenderer] into space_gen's standard +// [runCli] shell. The renderer matches this package's layout convention: +// everything lives under `lib/src/` (standard Dart internal-files layout), +// request/response DTOs owned by a single operation nest under a +// per-operation directory, domain models land in `lib/src/models/`, +// shared messages stay flat in `lib/src/messages/`. +// +// Usage (from the repo root): +// dart run packages/shorebird_code_push_protocol/tool/gen.dart \ +// -i https://api.shorebird.dev/openapi.json \ +// -o packages/shorebird_code_push_protocol +// +// The generator does not touch `lib/extensions/` or +// `lib/shorebird_code_push_protocol.dart`; those are hand-written and +// re-export the generated types. + +import 'package:space_gen/space_gen.dart'; + +class ShorebirdFileRenderer extends FileRenderer { + ShorebirdFileRenderer(super.config); + + @override + String modelPath(LayoutContext context) { + final snakeName = context.schema.snakeName; + final className = context.schema.typeName; + final isMessage = + className.endsWith('Request') || className.endsWith('Response'); + if (!isMessage) return 'src/models/$snakeName.dart'; + final base = _messageBaseName(snakeName); + if (context.operationSnakeNames.contains(base)) { + return 'src/messages/$base/$snakeName.dart'; + } + return 'src/messages/$snakeName.dart'; + } + + /// Route generated round-trip tests to `test/generated/` so they sit + /// alongside the hand-written tests at `test/src/` without colliding. + /// Mirrors [modelPath], just under a dedicated directory. + @override + String? testPath(LayoutContext context) { + final modelRelative = modelPath(context); + // Strip a leading `src/` — we already namespace under `generated/`. + final trimmed = modelRelative.startsWith('src/') + ? modelRelative.substring('src/'.length) + : modelRelative; + final withSuffix = trimmed.replaceFirst( + RegExp(r'\.dart$'), + '_test.dart', + ); + return 'test/generated/$withSuffix'; + } + + /// Tests import the hand-maintained top-level barrel, not the + /// generator's `api.dart` (which we don't emit — see below). + @override + String testBarrelImport() => 'shorebird_code_push_protocol.dart'; + + // Everything below is a no-op override: this package hand-maintains + // its pubspec, analysis config, HTTP client, auth, and top-level + // barrel. space_gen is only on the hook for models/messages/tests + // and the `model_helpers.dart` runtime library. + + @override + void renderPubspec() {} + + @override + void renderAnalysisOptions() {} + + @override + void renderGitignore() {} + + @override + void renderApiException() {} + + @override + void renderAuth() {} + + @override + void renderApiClient(RenderSpec spec) {} + + @override + List renderApis(List apis) => const []; + + @override + void renderClient(List apis, {required String specName}) {} + + @override + void renderPublicApi(Iterable apis, Iterable schemas) {} + + @override + void renderCspellConfig(List misspellings) {} + + /// Strip a trailing `_request`/`_response` (and any HTTP status code + /// inline-schema suffix like `200_response`) from [snake], returning + /// the operation-name portion. Non-matching input is returned as-is. + static String _messageBaseName(String snake) { + for (final suffix in const ['_request', '_response']) { + if (snake.endsWith(suffix)) { + var base = snake.substring(0, snake.length - suffix.length); + final match = RegExp(r'\d+$').firstMatch(base); + if (match != null) { + base = base.substring(0, match.start); + } + return base; + } + } + return snake; + } +} + +Future main(List arguments) => + runCli(arguments, fileRendererBuilder: ShorebirdFileRenderer.new); diff --git a/pubspec.lock b/pubspec.lock index 9090a179..a28c0dda 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -441,6 +441,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.5" + mustache_template: + dependency: transitive + description: + name: mustache_template + sha256: "544ff0b837836f5ad6b351e7a676ff7c2cad4fa412c465908aeb9358caddb6fc" + url: "https://pub.dev" + source: hosted + version: "2.0.4" node_preamble: dependency: transitive description: @@ -673,6 +681,15 @@ packages: url: "https://pub.dev" source: hosted version: "1.10.2" + space_gen: + dependency: transitive + description: + path: "." + ref: "58b4410a9b25bf58e3f76a4ae979cad52d4909cc" + resolved-ref: "58b4410a9b25bf58e3f76a4ae979cad52d4909cc" + url: "https://github.com/eseidel/space_gen.git" + source: git + version: "1.0.1" stack_trace: dependency: transitive description: @@ -761,6 +778,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.5.3" + version: + dependency: transitive + description: + name: version + sha256: "3d4140128e6ea10d83da32fef2fa4003fccbf6852217bb854845802f04191f94" + url: "https://pub.dev" + source: hosted + version: "3.0.2" very_good_analysis: dependency: "direct dev" description: