feat(shorebird_code_push_protocol): create package (#62)

This commit is contained in:
Felix Angelov
2023-03-14 10:37:10 -05:00
committed by GitHub
parent 3310aa1161
commit 25231b36c7
23 changed files with 533 additions and 5 deletions
+10 -5
View File
@@ -32,7 +32,7 @@ inputs:
platform:
required: false
type: string
default: "vm"
default: "vm"
runs:
using: "composite"
@@ -41,23 +41,28 @@ runs:
with:
sdk: ${{inputs.dart_sdk}}
- working-directory: ${{ inputs.working_directory }}
- name: Install Dependencies
working-directory: ${{ inputs.working_directory }}
shell: ${{ inputs.shell }}
run: dart pub get
- working-directory: ${{ inputs.working_directory }}
- name: Format
working-directory: ${{ inputs.working_directory }}
shell: ${{ inputs.shell }}
run: dart format --set-exit-if-changed .
- working-directory: ${{ inputs.working_directory }}
- name: Analyze
working-directory: ${{ inputs.working_directory }}
shell: ${{ inputs.shell }}
run: dart analyze --fatal-warnings ${{inputs.analyze_directories}}
- working-directory: ${{ inputs.working_directory }}
- name: Test
working-directory: ${{ inputs.working_directory }}
shell: ${{ inputs.shell }}
run: |
dart pub global activate coverage
dart test -j ${{inputs.concurrency}} --coverage=coverage --platform=${{inputs.platform}} && dart pub global run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=${{inputs.report_on}} --check-ignore
- uses: VeryGoodOpenSource/very_good_coverage@v2
with:
path: ${{inputs.working_directory}}/coverage/lcov.info
+3
View File
@@ -38,6 +38,9 @@ jobs:
shorebird_code_push_api_client:
- ./.github/actions/dart_package
- packages/shorebird_code_push_api_client/**
shorebird_code_push_protocol:
- ./.github/actions/dart_package
- packages/shorebird_code_push_protocol/**
- uses: dorny/paths-filter@v2
name: Verify Detection
+1
View File
@@ -26,6 +26,7 @@ This repository is a monorepo containing the following packages:
| ----------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
| [shorebird_cli](packages/shorebird_cli/README.md) | Command-line which allows developers to interact with various Shorebird services |
| [shorebird_code_push_api_client](packages/shorebird_code_push_api_client/README.md) | Dart library which allows Dart applications to interact with the ShoreBird CodePush API |
| [shorebird_code_push_protocol](packages/shorebird_code_push_protocol/README.md) | Dart library which contains common interfaces used by Shorebird CodePush |
| [shorebird_code_push_updater](updater/README.md) | Rust library which handles the CodePush logic and does the real update work |
For more information, please refer to the documentation for each package.
@@ -0,0 +1,8 @@
# See https://www.dartlang.org/guides/libraries/private-files
# Files and directories created by pub
.dart_tool/
.packages
build/
pubspec.lock
coverage/
@@ -0,0 +1,3 @@
## Shorebird CodePush Protocol
The Shorebird CodePush Protocol is a Dart library which contains common interfaces used by Shorebird CodePush.
@@ -0,0 +1 @@
include: package:very_good_analysis/analysis_options.4.0.0.yaml
@@ -0,0 +1,15 @@
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
@@ -0,0 +1,4 @@
/// The Shorebird CodePush Protocol
library shorebird_code_push_protocol;
export 'src/models/models.dart';
@@ -0,0 +1,26 @@
import 'package:json_annotation/json_annotation.dart';
import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart';
part 'account.g.dart';
/// {@template account}
/// A user account which contains zero or more apps.
/// {@endtemplate}
@JsonSerializable()
class Account {
/// {@macro account}
Account({required this.apiKey, List<App>? apps}) : apps = apps ?? [];
/// Converts a Map<String, dynamic> to a [Account]
factory Account.fromJson(Map<String, dynamic> json) =>
_$AccountFromJson(json);
/// Converts a [Account] to a Map<String, dynamic>
Map<String, dynamic> toJson() => _$AccountToJson(this);
/// List of apps associated with this account.
final List<App> apps;
/// The api key associated with this account.
final String apiKey;
}
@@ -0,0 +1,31 @@
// 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 'account.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
Account _$AccountFromJson(Map<String, dynamic> json) => $checkedCreate(
'Account',
json,
($checkedConvert) {
final val = Account(
apiKey: $checkedConvert('api_key', (v) => v as String),
apps: $checkedConvert(
'apps',
(v) => (v as List<dynamic>?)
?.map((e) => App.fromJson(e as Map<String, dynamic>))
.toList()),
);
return val;
},
fieldKeyMap: const {'apiKey': 'api_key'},
);
Map<String, dynamic> _$AccountToJson(Account instance) => <String, dynamic>{
'apps': instance.apps.map((e) => e.toJson()).toList(),
'api_key': instance.apiKey,
};
@@ -0,0 +1,26 @@
import 'package:json_annotation/json_annotation.dart';
import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart';
part 'app.g.dart';
/// {@template app}
/// A single app which contains zero or more releases.
/// {@endtemplate}
@JsonSerializable()
class App {
/// {@macro app}
App({required this.productId, List<Release>? releases})
: releases = releases ?? [];
/// Converts a Map<String, dynamic> to an [App]
factory App.fromJson(Map<String, dynamic> json) => _$AppFromJson(json);
/// Converts a [App] to a Map<String, dynamic>
Map<String, dynamic> toJson() => _$AppToJson(this);
/// The product ID of the app.
final String productId;
/// List of releases associated with this app.
final List<Release> releases;
}
@@ -0,0 +1,31 @@
// 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<String, dynamic> json) => $checkedCreate(
'App',
json,
($checkedConvert) {
final val = App(
productId: $checkedConvert('product_id', (v) => v as String),
releases: $checkedConvert(
'releases',
(v) => (v as List<dynamic>?)
?.map((e) => Release.fromJson(e as Map<String, dynamic>))
.toList()),
);
return val;
},
fieldKeyMap: const {'productId': 'product_id'},
);
Map<String, dynamic> _$AppToJson(App instance) => <String, dynamic>{
'product_id': instance.productId,
'releases': instance.releases.map((e) => e.toJson()).toList(),
};
@@ -0,0 +1,39 @@
import 'package:json_annotation/json_annotation.dart';
part 'artifact.g.dart';
/// {@template artifact}
/// An artifact represents the contents of an update (patch) for a specific
/// platform and architecture.
/// {@endtemplate}
@JsonSerializable()
class Artifact {
/// {@macro artifact}
const Artifact({
required this.arch,
required this.platform,
required this.url,
required this.hash,
});
/// Converts a Map<String, dynamic> to an [Artifact]
factory Artifact.fromJson(Map<String, dynamic> json) =>
_$ArtifactFromJson(json);
/// Converts an [Artifact] to a Map<String, dynamic>
Map<String, dynamic> toJson() => _$ArtifactToJson(this);
/// The architecture of the artifact.
/// e.g. arm64, x86_64
final String arch;
/// The platform of the artifact.
/// e.g. android, ios
final String platform;
/// The URL of the artifact.
final String url;
/// The hash of the artifact.
final String hash;
}
@@ -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 'artifact.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
Artifact _$ArtifactFromJson(Map<String, dynamic> json) => $checkedCreate(
'Artifact',
json,
($checkedConvert) {
final val = Artifact(
arch: $checkedConvert('arch', (v) => v as String),
platform: $checkedConvert('platform', (v) => v as String),
url: $checkedConvert('url', (v) => v as String),
hash: $checkedConvert('hash', (v) => v as String),
);
return val;
},
);
Map<String, dynamic> _$ArtifactToJson(Artifact instance) => <String, dynamic>{
'arch': instance.arch,
'platform': instance.platform,
'url': instance.url,
'hash': instance.hash,
};
@@ -0,0 +1,6 @@
export 'account.dart';
export 'app.dart';
export 'artifact.dart';
export 'patch.dart';
export 'registry.dart';
export 'release.dart';
@@ -0,0 +1,32 @@
import 'package:json_annotation/json_annotation.dart';
import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart';
part 'patch.g.dart';
/// {@template patch}
/// A single patch which contains zero or more artifacts.
/// {@endtemplate}
@JsonSerializable()
class Patch {
/// {@macro patch}
const Patch({
required this.number,
this.artifacts = const [],
this.channels = const [],
});
/// Converts a Map<String, dynamic> to a [Patch]
factory Patch.fromJson(Map<String, dynamic> json) => _$PatchFromJson(json);
/// Converts a [Patch] to a Map<String, dynamic>
Map<String, dynamic> toJson() => _$PatchToJson(this);
/// The patch number (newer patches are larger).
final int number;
/// The list of channels associated with this patch.
final List<String> channels;
/// List of artifacts associated with this patch.
final List<Artifact> artifacts;
}
@@ -0,0 +1,38 @@
// 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<String, dynamic> json) => $checkedCreate(
'Patch',
json,
($checkedConvert) {
final val = Patch(
number: $checkedConvert('number', (v) => v as int),
artifacts: $checkedConvert(
'artifacts',
(v) =>
(v as List<dynamic>?)
?.map((e) => Artifact.fromJson(e as Map<String, dynamic>))
.toList() ??
const []),
channels: $checkedConvert(
'channels',
(v) =>
(v as List<dynamic>?)?.map((e) => e as String).toList() ??
const []),
);
return val;
},
);
Map<String, dynamic> _$PatchToJson(Patch instance) => <String, dynamic>{
'number': instance.number,
'channels': instance.channels,
'artifacts': instance.artifacts.map((e) => e.toJson()).toList(),
};
@@ -0,0 +1,23 @@
import 'package:json_annotation/json_annotation.dart';
import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart';
part 'registry.g.dart';
/// {@template registry}
/// A collection of accounts and their respective apps
/// {@endtemplate}
@JsonSerializable()
class Registry {
/// {@macro registry}
const Registry({this.accounts = const []});
/// Converts a Map<String, dynamic> to a [Registry]
factory Registry.fromJson(Map<String, dynamic> json) =>
_$RegistryFromJson(json);
/// Converts a [Registry] to a Map<String, dynamic>
Map<String, dynamic> toJson() => _$RegistryToJson(this);
/// List of accounts associated with this registry.
final List<Account> accounts;
}
@@ -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 'registry.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
Registry _$RegistryFromJson(Map<String, dynamic> json) => $checkedCreate(
'Registry',
json,
($checkedConvert) {
final val = Registry(
accounts: $checkedConvert(
'accounts',
(v) =>
(v as List<dynamic>?)
?.map((e) => Account.fromJson(e as Map<String, dynamic>))
.toList() ??
const []),
);
return val;
},
);
Map<String, dynamic> _$RegistryToJson(Registry instance) => <String, dynamic>{
'accounts': instance.accounts.map((e) => e.toJson()).toList(),
};
@@ -0,0 +1,27 @@
import 'package:json_annotation/json_annotation.dart';
import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart';
part 'release.g.dart';
/// {@template release}
/// A single release which contains zero or more patches.
/// {@endtemplate}
@JsonSerializable()
class Release {
/// {@macro release}
Release({required this.version, List<Patch>? patches})
: patches = patches ?? [];
/// Converts a Map<String, dynamic> to a [Release]
factory Release.fromJson(Map<String, dynamic> json) =>
_$ReleaseFromJson(json);
/// Converts a [Release] to a Map<String, dynamic>
Map<String, dynamic> toJson() => _$ReleaseToJson(this);
/// The version of the release.
final String version;
/// List of patches associated with this release.
final List<Patch> patches;
}
@@ -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 'release.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
Release _$ReleaseFromJson(Map<String, dynamic> json) => $checkedCreate(
'Release',
json,
($checkedConvert) {
final val = Release(
version: $checkedConvert('version', (v) => v as String),
patches: $checkedConvert(
'patches',
(v) => (v as List<dynamic>?)
?.map((e) => Patch.fromJson(e as Map<String, dynamic>))
.toList()),
);
return val;
},
);
Map<String, dynamic> _$ReleaseToJson(Release instance) => <String, dynamic>{
'version': instance.version,
'patches': instance.patches.map((e) => e.toJson()).toList(),
};
@@ -0,0 +1,20 @@
name: shorebird_code_push_protocol
description: Library which contains common interfaces used by Shorebird CodePush
version: 0.1.0+1
repository: https://github.com/shorebirdtech/shorebird
publish_to: none
environment:
sdk: ">=2.19.0 <3.0.0"
dependencies:
json_annotation: ^4.8.0
dev_dependencies:
build_runner: ^2.0.0
json_serializable: ^6.6.1
mocktail: ^0.3.0
path: ^1.8.3
test: ^1.19.2
very_good_analysis: ^4.0.0
@@ -0,0 +1,99 @@
import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart';
import 'package:test/test.dart';
void main() {
group('Registry', () {
test('can be (de)serialized', () {
final registry = Registry(
accounts: [
Account(
apiKey: 'api_key1',
apps: [
App(
productId: 'app1',
releases: [
Release(
version: '1.0.0',
patches: [
const Patch(
number: 1,
artifacts: [
Artifact(
arch: 'aarm64',
platform: 'android',
url: 'localhost',
hash: '#',
)
],
channels: ['stable'],
),
const Patch(
number: 2,
artifacts: [
Artifact(
arch: 'aarm64',
platform: 'android',
url: 'localhost',
hash: '#',
)
],
channels: ['stable'],
)
],
),
Release(version: '1.0.1'),
],
),
App(productId: 'app2'),
],
),
Account(
apiKey: 'api_key2',
apps: [
App(
productId: 'app2',
releases: [
Release(
version: '1.0.0',
patches: [
const Patch(
number: 1,
artifacts: [
Artifact(
arch: 'aarm64',
platform: 'android',
url: 'localhost',
hash: '#',
)
],
channels: ['stable'],
),
const Patch(
number: 2,
artifacts: [
Artifact(
arch: 'aarm64',
platform: 'android',
url: 'localhost',
hash: '#',
)
],
channels: ['stable'],
)
],
),
Release(version: '2.0.0'),
],
),
],
),
],
);
expect(
Registry.fromJson(registry.toJson()).toJson(),
equals(registry.toJson()),
);
});
});
}