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 e4082778..13d79b6f 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 @@ -62,7 +62,12 @@ void main() { ), ); const appId = 'test-app-id'; - const app = AppMetadata(appId: appId, displayName: 'Test App'); + final app = AppMetadata( + appId: appId, + displayName: 'Test App', + createdAt: DateTime(2023), + updatedAt: DateTime(2023), + ); const channelName = 'my-channel'; const channel = Channel(id: 0, appId: appId, name: channelName); const patchId = 1; 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 876ef5e7..c02df40e 100644 --- a/packages/shorebird_cli/test/src/commands/init_command_test.dart +++ b/packages/shorebird_cli/test/src/commands/init_command_test.dart @@ -806,7 +806,12 @@ flavors: when(() => codePushClientWrapper.getApp(appId: any(named: 'appId'))) .thenAnswer( - (_) async => const AppMetadata(appId: appId, displayName: appName), + (_) async => AppMetadata( + appId: appId, + displayName: appName, + createdAt: DateTime(2023), + updatedAt: DateTime(2023), + ), ); when( () => diff --git a/packages/shorebird_cli/test/src/commands/patch/patch_aar_command_test.dart b/packages/shorebird_cli/test/src/commands/patch/patch_aar_command_test.dart index 741bdf65..5258c5bc 100644 --- a/packages/shorebird_cli/test/src/commands/patch/patch_aar_command_test.dart +++ b/packages/shorebird_cli/test/src/commands/patch/patch_aar_command_test.dart @@ -41,7 +41,12 @@ void main() { const releasePlatform = ReleasePlatform.android; const channelName = 'stable'; const appDisplayName = 'Test App'; - const appMetadata = AppMetadata(appId: appId, displayName: appDisplayName); + final appMetadata = AppMetadata( + appId: appId, + displayName: appDisplayName, + createdAt: DateTime(2023), + updatedAt: DateTime(2023), + ); const androidPackageName = 'com.example.my_flutter_module'; const releaseArtifact = ReleaseArtifact( id: 0, diff --git a/packages/shorebird_cli/test/src/commands/patch/patch_android_command_test.dart b/packages/shorebird_cli/test/src/commands/patch/patch_android_command_test.dart index 7e963dd4..60e03caa 100644 --- a/packages/shorebird_cli/test/src/commands/patch/patch_android_command_test.dart +++ b/packages/shorebird_cli/test/src/commands/patch/patch_android_command_test.dart @@ -44,7 +44,12 @@ void main() { const releasePlatform = ReleasePlatform.android; const channelName = 'stable'; const appDisplayName = 'Test App'; - const app = AppMetadata(appId: appId, displayName: appDisplayName); + final appMetadata = AppMetadata( + appId: appId, + displayName: appDisplayName, + createdAt: DateTime(2023), + updatedAt: DateTime(2023), + ); const releaseArtifact = ReleaseArtifact( id: 0, releaseId: 0, @@ -284,7 +289,7 @@ flutter: () => codePushClientWrapper.getApp( appId: any(named: 'appId'), ), - ).thenAnswer((_) async => app); + ).thenAnswer((_) async => appMetadata); when( () => codePushClientWrapper.getRelease( appId: any(named: 'appId'), diff --git a/packages/shorebird_cli/test/src/commands/patch/patch_ios_command_test.dart b/packages/shorebird_cli/test/src/commands/patch/patch_ios_command_test.dart index e36813f3..9a5bd9fc 100644 --- a/packages/shorebird_cli/test/src/commands/patch/patch_ios_command_test.dart +++ b/packages/shorebird_cli/test/src/commands/patch/patch_ios_command_test.dart @@ -90,7 +90,12 @@ flutter: assets: - shorebird.yaml'''; - const appMetadata = AppMetadata(appId: appId, displayName: appDisplayName); + final appMetadata = AppMetadata( + appId: appId, + displayName: appDisplayName, + createdAt: DateTime(2023), + updatedAt: DateTime(2023), + ); const ipaArtifact = ReleaseArtifact( id: 0, releaseId: 0, diff --git a/packages/shorebird_cli/test/src/commands/patch/patch_ios_framework_command_test.dart b/packages/shorebird_cli/test/src/commands/patch/patch_ios_framework_command_test.dart index f4f026b3..af78073d 100644 --- a/packages/shorebird_cli/test/src/commands/patch/patch_ios_framework_command_test.dart +++ b/packages/shorebird_cli/test/src/commands/patch/patch_ios_framework_command_test.dart @@ -44,7 +44,12 @@ environment: flutter: assets: - shorebird.yaml'''; - const appMetadata = AppMetadata(appId: appId, displayName: appDisplayName); + final appMetadata = AppMetadata( + appId: appId, + displayName: appDisplayName, + createdAt: DateTime(2023), + updatedAt: DateTime(2023), + ); const arch = 'aarch64'; const xcframeworkArtifact = ReleaseArtifact( id: 0, diff --git a/packages/shorebird_cli/test/src/commands/release/release_aar_command_test.dart b/packages/shorebird_cli/test/src/commands/release/release_aar_command_test.dart index f29e5af7..20103911 100644 --- a/packages/shorebird_cli/test/src/commands/release/release_aar_command_test.dart +++ b/packages/shorebird_cli/test/src/commands/release/release_aar_command_test.dart @@ -30,7 +30,12 @@ void main() { const appId = 'test-app-id'; const shorebirdYaml = ShorebirdYaml(appId: appId); const androidPackageName = 'com.example.my_flutter_module'; - const appMetadata = AppMetadata(appId: appId, displayName: appDisplayName); + final appMetadata = AppMetadata( + appId: appId, + displayName: appDisplayName, + createdAt: DateTime(2023), + updatedAt: DateTime(2023), + ); const flutterRevision = '83305b5088e6fe327fb3334a73ff190828d85713'; const versionName = '1.2.3'; const versionCode = '1'; diff --git a/packages/shorebird_cli/test/src/commands/release/release_android_command_test.dart b/packages/shorebird_cli/test/src/commands/release/release_android_command_test.dart index 691eda96..43ec7637 100644 --- a/packages/shorebird_cli/test/src/commands/release/release_android_command_test.dart +++ b/packages/shorebird_cli/test/src/commands/release/release_android_command_test.dart @@ -38,7 +38,12 @@ void main() { const appDisplayName = 'Test App'; const arch = 'aarch64'; const releasePlatform = ReleasePlatform.android; - const appMetadata = AppMetadata(appId: appId, displayName: appDisplayName); + final appMetadata = AppMetadata( + appId: appId, + displayName: appDisplayName, + createdAt: DateTime(2023), + updatedAt: DateTime(2023), + ); const release = Release( id: 0, appId: appId, diff --git a/packages/shorebird_cli/test/src/commands/release/release_ios_command_test.dart b/packages/shorebird_cli/test/src/commands/release/release_ios_command_test.dart index d0c34090..e5bd0df8 100644 --- a/packages/shorebird_cli/test/src/commands/release/release_ios_command_test.dart +++ b/packages/shorebird_cli/test/src/commands/release/release_ios_command_test.dart @@ -36,7 +36,12 @@ void main() { const arch = 'armv7'; const releasePlatform = ReleasePlatform.ios; const ipaPath = 'build/ios/ipa/Runner.ipa'; - const appMetadata = AppMetadata(appId: appId, displayName: appDisplayName); + final appMetadata = AppMetadata( + appId: appId, + displayName: appDisplayName, + createdAt: DateTime(2023), + updatedAt: DateTime(2023), + ); const release = Release( id: 0, appId: appId, diff --git a/packages/shorebird_cli/test/src/commands/release/release_ios_framework_command_test.dart b/packages/shorebird_cli/test/src/commands/release/release_ios_framework_command_test.dart index 4f6a1e41..2a179d77 100644 --- a/packages/shorebird_cli/test/src/commands/release/release_ios_framework_command_test.dart +++ b/packages/shorebird_cli/test/src/commands/release/release_ios_framework_command_test.dart @@ -33,7 +33,12 @@ void main() { const version = '$versionName+$versionCode'; const appDisplayName = 'Test App'; const releasePlatform = ReleasePlatform.ios; - const appMetadata = AppMetadata(appId: appId, displayName: appDisplayName); + final appMetadata = AppMetadata( + appId: appId, + displayName: appDisplayName, + createdAt: DateTime(2023), + updatedAt: DateTime(2023), + ); const release = Release( id: 0, appId: appId, 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 9847b47f..95a2b9a4 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 @@ -402,10 +402,10 @@ class CodePushClient { throw _parseErrorResponse(response.statusCode, response.body); } - final apps = json.decode(response.body) as List; - return apps - .map((app) => AppMetadata.fromJson(app as Map)) - .toList(); + final decoded = GetAppsResponse.fromJson( + json.decode(response.body) as Map, + ); + return decoded.apps; } /// List all channels for the provided [appId]. diff --git a/packages/shorebird_code_push_client/lib/src/version.dart b/packages/shorebird_code_push_client/lib/src/version.dart index 664d8961..957ca59e 100644 --- a/packages/shorebird_code_push_client/lib/src/version.dart +++ b/packages/shorebird_code_push_client/lib/src/version.dart @@ -1,2 +1,2 @@ // Generated code. Do not modify. -const packageVersion = '0.5.0+1'; +const packageVersion = '0.6.0+1'; diff --git a/packages/shorebird_code_push_client/pubspec.yaml b/packages/shorebird_code_push_client/pubspec.yaml index 1169e324..4c7c2b5c 100644 --- a/packages/shorebird_code_push_client/pubspec.yaml +++ b/packages/shorebird_code_push_client/pubspec.yaml @@ -1,6 +1,6 @@ name: shorebird_code_push_client description: Library which allows Dart applications to interact with the ShoreBird CodePush API -version: 0.5.0+1 +version: 0.6.0+1 repository: https://github.com/shorebirdtech/shorebird publish_to: none 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 54234626..f8c08ec6 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 @@ -1580,9 +1580,12 @@ void main() { }); test('completes when request succeeds (empty)', () async { + final expected = []; when(() => httpClient.send(any())).thenAnswer( (_) async => http.StreamedResponse( - Stream.value(utf8.encode(json.encode([]))), + Stream.value( + utf8.encode(json.encode(GetAppsResponse(apps: expected))), + ), HttpStatus.ok, ), ); @@ -1593,13 +1596,25 @@ void main() { test('completes when request succeeds (populated)', () async { final expected = [ - AppMetadata(appId: '1', displayName: 'Shorebird Example'), - AppMetadata(appId: '2', displayName: 'Shorebird Clock'), + AppMetadata( + appId: '1', + displayName: 'Shorebird Example', + createdAt: DateTime(2022), + updatedAt: DateTime(2023), + ), + AppMetadata( + appId: '2', + displayName: 'Shorebird Clock', + createdAt: DateTime(2022), + updatedAt: DateTime(2023), + ), ]; when(() => httpClient.send(any())).thenAnswer( (_) async => http.StreamedResponse( - Stream.value(utf8.encode(json.encode(expected))), + Stream.value( + utf8.encode(json.encode(GetAppsResponse(apps: expected))), + ), HttpStatus.ok, ), ); 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 new file mode 100644 index 00000000..ab943ad0 --- /dev/null +++ b/packages/shorebird_code_push_protocol/lib/src/messages/get_apps/get_apps.dart @@ -0,0 +1 @@ +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 new file mode 100644 index 00000000..aca7bc8e --- /dev/null +++ b/packages/shorebird_code_push_protocol/lib/src/messages/get_apps/get_apps_response.dart @@ -0,0 +1,23 @@ +import 'package:json_annotation/json_annotation.dart'; +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; + +part 'get_apps_response.g.dart'; + +/// {@template get_apps_response} +/// The response body for GET /api/v1/apps +/// {@endtemplate} +@JsonSerializable() +class GetAppsResponse { + /// {@macro get_apps_response} + const GetAppsResponse({required this.apps}); + + /// Converts a Map to a [GetAppsResponse]. + factory GetAppsResponse.fromJson(Map json) => + _$GetAppsResponseFromJson(json); + + /// Converts a [GetAppsResponse] to a Map. + Json toJson() => _$GetAppsResponseToJson(this); + + /// The list of apps. + final List 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 new file mode 100644 index 00000000..2fd35996 --- /dev/null +++ b/packages/shorebird_code_push_protocol/lib/src/messages/get_apps/get_apps_response.g.dart @@ -0,0 +1,30 @@ +// 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/messages.dart b/packages/shorebird_code_push_protocol/lib/src/messages/messages.dart index e37612f4..0dcf5fc8 100644 --- a/packages/shorebird_code_push_protocol/lib/src/messages/messages.dart +++ b/packages/shorebird_code_push_protocol/lib/src/messages/messages.dart @@ -10,6 +10,7 @@ export 'create_payment_link/create_payment_link.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_overages/get_overages.dart'; export 'get_release_artifacts/get_release_artifacts.dart'; export 'get_release_patches/get_release_patches.dart'; 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 cf02ed9f..f164cc4c 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 @@ -11,6 +11,8 @@ class AppMetadata { const AppMetadata({ required this.appId, required this.displayName, + required this.createdAt, + required this.updatedAt, this.latestReleaseVersion, this.latestPatchNumber, }); @@ -33,4 +35,10 @@ class AppMetadata { /// The latest patch number of the app. final int? latestPatchNumber; + + /// The date and time the app was created. + final DateTime createdAt; + + /// The date and time the app was last updated. + final DateTime 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 index b7f571f4..9a4240c8 100644 --- 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 @@ -15,6 +15,10 @@ AppMetadata _$AppMetadataFromJson(Map json) => $checkedCreate( 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: @@ -25,6 +29,8 @@ AppMetadata _$AppMetadataFromJson(Map json) => $checkedCreate( fieldKeyMap: const { 'appId': 'app_id', 'displayName': 'display_name', + 'createdAt': 'created_at', + 'updatedAt': 'updated_at', 'latestReleaseVersion': 'latest_release_version', 'latestPatchNumber': 'latest_patch_number' }, @@ -36,4 +42,6 @@ Map _$AppMetadataToJson(AppMetadata instance) => '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/pubspec.yaml b/packages/shorebird_code_push_protocol/pubspec.yaml index a286a07a..dda08c42 100644 --- a/packages/shorebird_code_push_protocol/pubspec.yaml +++ b/packages/shorebird_code_push_protocol/pubspec.yaml @@ -9,7 +9,7 @@ environment: sdk: ">=3.0.0 <4.0.0" dependencies: - json_annotation: ^4.8.0 + json_annotation: ^4.8.1 money2: ^3.4.1 dev_dependencies: diff --git a/packages/shorebird_code_push_protocol/test/src/messages/get_apps/get_apps_response_test.dart b/packages/shorebird_code_push_protocol/test/src/messages/get_apps/get_apps_response_test.dart new file mode 100644 index 00000000..81d5c8f8 --- /dev/null +++ b/packages/shorebird_code_push_protocol/test/src/messages/get_apps/get_apps_response_test.dart @@ -0,0 +1,23 @@ +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; +import 'package:test/test.dart'; + +void main() { + group(GetAppsResponse, () { + test('can be (de)serialized', () { + final response = GetAppsResponse( + apps: [ + AppMetadata( + appId: 'app-id', + displayName: 'display-name', + createdAt: DateTime(2022), + updatedAt: DateTime(2023), + ) + ], + ); + expect( + GetAppsResponse.fromJson(response.toJson()).toJson(), + equals(response.toJson()), + ); + }); + }); +} 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 993da2c9..d4fb97f4 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 @@ -4,11 +4,13 @@ import 'package:test/test.dart'; void main() { group(AppMetadata, () { test('can be (de)serialized', () { - const appMetadata = AppMetadata( + final appMetadata = AppMetadata( appId: '30370f27-dbf1-4673-8b20-fb096e38dffa', displayName: 'My App', latestReleaseVersion: '1.0.0', latestPatchNumber: 1, + createdAt: DateTime(2022), + updatedAt: DateTime(2023), ); expect( AppMetadata.fromJson(appMetadata.toJson()).toJson(),