chore: rename product_id to app_id (#77)

This commit is contained in:
Felix Angelov
2023-03-15 14:11:13 -05:00
committed by GitHub
parent 5425f09d46
commit 62bed70bf5
29 changed files with 146 additions and 145 deletions
+33 -28
View File
@@ -1,39 +1,44 @@
## A reminder why
* We're here to make multi-platform the default.
* We believe Flutter is that default, but has missing pieces for enterprises.
* The first hole we're filling is the ability to push updates to Flutter apps.
- We're here to make multi-platform the default.
- We believe Flutter is that default, but has missing pieces for enterprises.
- The first hole we're filling is the ability to push updates to Flutter apps.
## This Week's Demo
* Platform support (e.g. push to both arm7 and arm64)
* API Keys and/or product ids (allows multiple users)
* Teach the server how to decline to update (e.g. platform/version mismatch).
* Instructions on how to build/use.
- Platform support (e.g. push to both arm7 and arm64)
- API Keys and/or app ids (allows multiple users)
- Teach the server how to decline to update (e.g. platform/version mismatch).
- Instructions on how to build/use.
## User journey
Someone can:
* download and install Shorebird.
* `shorebird build` their existing Flutter app.
* Push an update to their app.
- download and install Shorebird.
- `shorebird build` their existing Flutter app.
- Push an update to their app.
## Shipping to users (first, do no harm)
* Need a way to know if the update failed (and both report it and roll back?)
* Need to not send updates to incompatible devices or base versions.
* Do we need to worry about different chipsets?
* How do we educate users/developers about data storage updates (e.g. updating a database schema locally) and how that affects version compatibility / ability to roll back?
* How does the Dart code know that it's running a patched version?
- Need a way to know if the update failed (and both report it and roll back?)
- Need to not send updates to incompatible devices or base versions.
- Do we need to worry about different chipsets?
- How do we educate users/developers about data storage updates (e.g. updating a database schema locally) and how that affects version compatibility / ability to roll back?
- How does the Dart code know that it's running a patched version?
## Later
* Way to see what builds have been published so far.
* See what % of devices are running what builds.
* Make package:updater API work from Dart
* Example of using Dart API from Dart/Flutter.
* Ability to roll back to past push.
* Build update from source (in the cloud).
* GitHub integration / action trigger.
* Quantify update download sizes.
* Be able to create an account / API key.
* Web interface to see pushes?
* Security (signing, 2FA, 2-person approval, etc.)
* Quantify how much bandwidth a push will use.
* What % of device population has taken push.
- Way to see what builds have been published so far.
- See what % of devices are running what builds.
- Make package:updater API work from Dart
- Example of using Dart API from Dart/Flutter.
- Ability to roll back to past push.
- Build update from source (in the cloud).
- GitHub integration / action trigger.
- Quantify update download sizes.
- Be able to create an account / API key.
- Web interface to see pushes?
- Security (signing, 2FA, 2-person approval, etc.)
- Quantify how much bandwidth a push will use.
- What % of device population has taken push.
+1 -1
View File
@@ -1 +1 @@
product_id: shorebird-counter
app_id: shorebird-counter
+2 -2
View File
@@ -76,7 +76,7 @@ shorebird logout
### Create App
To create an app use the `shorebird apps create` command. An app-id can be specified as a CLI option but shorebird will default to the product_id defined in the `shorebird.yaml`
To create an app use the `shorebird apps create` command. An app-id can be specified as a CLI option but shorebird will default to the app_id defined in the `shorebird.yaml`
```bash
# Create an app using default app id
@@ -96,7 +96,7 @@ Created new app: my-app-id
### Delete App
To delete an existing app on Shorebird, use the `shorebird apps delete` command. An app-id can be specified as a CLI option but shorebird will default to the product_id defined in the `shorebird.yaml`
To delete an existing app on Shorebird, use the `shorebird apps delete` command. An app-id can be specified as a CLI option but shorebird will default to the app_id defined in the `shorebird.yaml`
```bash
# Create an app using default app id
@@ -20,7 +20,7 @@ class CreateAppCommand extends ShorebirdCommand with ShorebirdConfigMixin {
'app-id',
help: '''
The unique application identifier.
Defaults to the product_id in "shorebird.yaml".''',
Defaults to the app_id in "shorebird.yaml".''',
);
}
@@ -38,34 +38,34 @@ Defaults to the product_id in "shorebird.yaml".''',
return ExitCode.noUser.code;
}
final appId = results['app-id'] as String?;
late final String productId;
final appIdArg = results['app-id'] as String?;
late final String appId;
if (appId == null) {
String? defaultProductId;
if (appIdArg == null) {
String? defaultAppId;
try {
defaultProductId = getShorebirdYaml()?.productId;
defaultAppId = getShorebirdYaml()?.appId;
} catch (_) {}
productId = logger.prompt(
appId = logger.prompt(
'${lightGreen.wrap('?')} Enter the App ID',
defaultValue: defaultProductId,
defaultValue: defaultAppId,
);
} else {
productId = appId;
appId = appIdArg;
}
final client = buildCodePushClient(apiKey: session.apiKey);
try {
await client.createApp(productId: productId);
await client.createApp(appId: appId);
} catch (error) {
logger.err('Unable to create app\n$error');
return ExitCode.software.code;
}
logger.info(
'${lightGreen.wrap('Created new app: ${cyan.wrap(productId)}')}',
'${lightGreen.wrap('Created new app: ${cyan.wrap(appId)}')}',
);
return ExitCode.success.code;
@@ -20,7 +20,7 @@ class DeleteAppCommand extends ShorebirdCommand with ShorebirdConfigMixin {
'app-id',
help: '''
The unique application identifier.
Defaults to the product_id in "shorebird.yaml".''',
Defaults to the app_id in "shorebird.yaml".''',
);
}
@@ -38,21 +38,21 @@ Defaults to the product_id in "shorebird.yaml".''',
return ExitCode.noUser.code;
}
final appId = results['app-id'] as String?;
late final String productId;
final appIdArg = results['app-id'] as String?;
late final String appId;
if (appId == null) {
String? defaultProductId;
if (appIdArg == null) {
String? defaultAppId;
try {
defaultProductId = getShorebirdYaml()?.productId;
defaultAppId = getShorebirdYaml()?.appId;
} catch (_) {}
productId = logger.prompt(
appId = logger.prompt(
'${lightGreen.wrap('?')} Enter the App ID',
defaultValue: defaultProductId,
defaultValue: defaultAppId,
);
} else {
productId = appId;
appId = appIdArg;
}
final client = buildCodePushClient(apiKey: session.apiKey);
@@ -64,14 +64,14 @@ Defaults to the product_id in "shorebird.yaml".''',
}
try {
await client.deleteApp(productId: productId);
await client.deleteApp(appId: appId);
} catch (error) {
logger.err('Unable to delete app\n$error');
return ExitCode.software.code;
}
logger.info(
'${lightGreen.wrap('Deleted app: ${cyan.wrap(productId)}')}',
'${lightGreen.wrap('Deleted app: ${cyan.wrap(appId)}')}',
);
return ExitCode.success.code;
@@ -67,6 +67,6 @@ extension on App {
final latestPatchPart =
latestPatch != null ? '(patch #${latestPatch.number})' : '';
return '$productId: $latestReleasePart $latestPatchPart';
return '$appId: $latestReleasePart $latestPatchPart';
}
}
@@ -83,7 +83,7 @@ For more information about Shorebird, visit ${link(uri: Uri.parse('https://shore
}
ShorebirdYaml _addShorebirdYamlToProject() {
final productId = buildUuid();
final appId = buildUuid();
File(
p.join(Directory.current.path, 'shorebird.yaml'),
).writeAsStringSync('''
@@ -91,10 +91,10 @@ For more information about Shorebird, visit ${link(uri: Uri.parse('https://shore
# Learn more at https://shorebird.dev
# This is the unique identifier for your app.
product_id: $productId
app_id: $appId
''');
return ShorebirdYaml(productId: productId);
return ShorebirdYaml(appId: appId);
}
void _addShorebirdYamlToPubspecAssets() {
@@ -71,13 +71,13 @@ class PublishCommand extends ShorebirdCommand with ShorebirdConfigMixin {
final shorebirdYaml = getShorebirdYaml()!;
final codePushClient = buildCodePushClient(apiKey: session.apiKey);
logger.detail(
'''Deploying ${artifact.path} to ${shorebirdYaml.productId} (${pubspecYaml.version})''',
'''Deploying ${artifact.path} to ${shorebirdYaml.appId} (${pubspecYaml.version})''',
);
final version = pubspecYaml.version!;
await codePushClient.createPatch(
artifactPath: artifact.path,
baseVersion: '${version.major}.${version.minor}.${version.patch}',
productId: shorebirdYaml.productId,
appId: shorebirdYaml.appId,
channel: 'stable',
);
} catch (error) {
@@ -8,10 +8,10 @@ part 'shorebird_yaml.g.dart';
createToJson: false,
)
class ShorebirdYaml {
const ShorebirdYaml({required this.productId});
const ShorebirdYaml({required this.appId});
factory ShorebirdYaml.fromJson(Map<dynamic, dynamic> json) =>
_$ShorebirdYamlFromJson(json);
final String productId;
final String appId;
}
@@ -14,12 +14,12 @@ ShorebirdYaml _$ShorebirdYamlFromJson(Map json) => $checkedCreate(
($checkedConvert) {
$checkKeys(
json,
allowedKeys: const ['product_id'],
allowedKeys: const ['app_id'],
);
final val = ShorebirdYaml(
productId: $checkedConvert('product_id', (v) => v as String),
appId: $checkedConvert('app_id', (v) => v as String),
);
return val;
},
fieldKeyMap: const {'productId': 'product_id'},
fieldKeyMap: const {'appId': 'app_id'},
);
@@ -18,7 +18,7 @@ class _MockLogger extends Mock implements Logger {}
void main() {
group('create', () {
const apiKey = 'test-api-key';
const productId = 'example';
const appId = 'example';
const session = Session(apiKey: apiKey);
late ArgResults argResults;
@@ -52,32 +52,32 @@ void main() {
});
test('prompts for app-id when not provided', () async {
when(() => logger.prompt(any())).thenReturn(productId);
when(() => logger.prompt(any())).thenReturn(appId);
await command.run();
verify(() => logger.prompt(any())).called(1);
verify(() => codePushClient.createApp(productId: productId)).called(1);
verify(() => codePushClient.createApp(appId: appId)).called(1);
});
test('uses provided app-id when provided', () async {
when(() => argResults['app-id']).thenReturn(productId);
when(() => argResults['app-id']).thenReturn(appId);
await command.run();
verifyNever(() => logger.prompt(any()));
verify(() => codePushClient.createApp(productId: productId)).called(1);
verify(() => codePushClient.createApp(appId: appId)).called(1);
});
test('returns success when app is created', () async {
when(() => argResults['app-id']).thenReturn(productId);
when(() => argResults['app-id']).thenReturn(appId);
when(
() => codePushClient.createApp(productId: productId),
() => codePushClient.createApp(appId: appId),
).thenAnswer((_) async {});
final result = await command.run();
expect(result, ExitCode.success.code);
});
test('returns software error when app creation fails', () async {
when(() => argResults['app-id']).thenReturn(productId);
when(() => argResults['app-id']).thenReturn(appId);
when(
() => codePushClient.createApp(productId: productId),
() => codePushClient.createApp(appId: appId),
).thenThrow(Exception());
final result = await command.run();
expect(result, ExitCode.software.code);
@@ -18,7 +18,7 @@ class _MockLogger extends Mock implements Logger {}
void main() {
group('delete', () {
const apiKey = 'test-api-key';
const productId = 'example';
const appId = 'example';
const session = Session(apiKey: apiKey);
late ArgResults argResults;
@@ -56,32 +56,32 @@ void main() {
test('prompts for app-id when not provided', () async {
when(() => logger.confirm(any())).thenReturn(false);
when(() => logger.prompt(any())).thenReturn(productId);
when(() => logger.prompt(any())).thenReturn(appId);
await command.run();
verify(() => logger.prompt(any())).called(1);
});
test('uses provided app-id when provided', () async {
when(() => logger.confirm(any())).thenReturn(false);
when(() => argResults['app-id']).thenReturn(productId);
when(() => argResults['app-id']).thenReturn(appId);
await command.run();
verifyNever(() => logger.prompt(any()));
});
test('aborts when user does not confirm', () async {
when(() => logger.confirm(any())).thenReturn(false);
when(() => argResults['app-id']).thenReturn(productId);
when(() => argResults['app-id']).thenReturn(appId);
final result = await command.run();
expect(result, ExitCode.success.code);
verifyNever(() => codePushClient.deleteApp(productId: productId));
verifyNever(() => codePushClient.deleteApp(appId: appId));
verify(() => logger.info('Aborted.')).called(1);
});
test('returns success when app is deleted', () async {
when(() => logger.confirm(any())).thenReturn(true);
when(() => argResults['app-id']).thenReturn(productId);
when(() => argResults['app-id']).thenReturn(appId);
when(
() => codePushClient.deleteApp(productId: productId),
() => codePushClient.deleteApp(appId: appId),
).thenAnswer((_) async {});
final result = await command.run();
expect(result, ExitCode.success.code);
@@ -89,9 +89,9 @@ void main() {
test('returns software error when app deletion fails', () async {
when(() => logger.confirm(any())).thenReturn(true);
when(() => argResults['app-id']).thenReturn(productId);
when(() => argResults['app-id']).thenReturn(appId);
when(
() => codePushClient.deleteApp(productId: productId),
() => codePushClient.deleteApp(appId: appId),
).thenThrow(Exception());
final result = await command.run();
expect(result, ExitCode.software.code);
@@ -58,7 +58,7 @@ void main() {
test('returns ExitCode.success when apps are not empty', () async {
final apps = [
App(
productId: 'shorebird-counter',
appId: 'shorebird-counter',
releases: [
Release(
version: '1.0.0',
@@ -18,7 +18,7 @@ name: example
version: $version
environment:
sdk: ">=2.19.0 <3.0.0"''';
const productId = 'test-product-id';
const appId = 'test-app-id';
late Logger logger;
late Progress progress;
@@ -27,10 +27,7 @@ environment:
setUp(() {
logger = _MockLogger();
progress = _MockProgress();
command = InitCommand(
logger: logger,
buildUuid: () => productId,
);
command = InitCommand(logger: logger, buildUuid: () => appId);
when(() => logger.progress(any())).thenReturn(progress);
});
@@ -77,21 +74,21 @@ environment:
});
test('detects existing shorebird.yaml', () async {
const existingProductId = 'existing-product-id';
const existingAppId = 'existing-app-id';
final tempDir = Directory.systemTemp.createTempSync();
File(
p.join(tempDir.path, 'pubspec.yaml'),
).writeAsStringSync(pubspecYamlContent);
File(
p.join(tempDir.path, 'shorebird.yaml'),
).writeAsStringSync('product_id: $existingProductId');
).writeAsStringSync('app_id: $existingAppId');
await IOOverrides.runZoned(
command.run,
getCurrentDirectory: () => tempDir,
);
expect(
File(p.join(tempDir.path, 'shorebird.yaml')).readAsStringSync(),
contains('product_id: $existingProductId'),
contains('app_id: $existingAppId'),
);
verify(() => progress.update('"shorebird.yaml" already exists.'));
});
@@ -107,7 +104,7 @@ environment:
);
expect(
File(p.join(tempDir.path, 'shorebird.yaml')).readAsStringSync(),
contains('product_id: $productId'),
contains('app_id: $appId'),
);
});
@@ -127,7 +124,7 @@ flutter:
);
expect(
File(p.join(tempDir.path, 'shorebird.yaml')).readAsStringSync(),
contains('product_id: $productId'),
contains('app_id: $appId'),
);
verify(
() => progress.update(
@@ -29,7 +29,7 @@ class _FakeCommandRunner extends Fake implements CommandRunner<int> {
void main() {
group('publish', () {
const session = Session(apiKey: 'test-api-key');
const productId = 'test-product-id';
const appId = 'test-app-id';
const version = '1.2.3';
const pubspecYamlContent = '''
name: example
@@ -54,7 +54,7 @@ flutter:
).writeAsStringSync(pubspecYamlContent);
File(
p.join(tempDir.path, 'shorebird.yaml'),
).writeAsStringSync('product_id: $productId');
).writeAsStringSync('app_id: $appId');
return tempDir;
}
@@ -79,7 +79,7 @@ flutter:
baseVersion: any(named: 'baseVersion'),
artifactPath: any(named: 'artifactPath'),
channel: any(named: 'channel'),
productId: any(named: 'productId'),
appId: any(named: 'appId'),
),
).thenAnswer((_) async {});
});
@@ -159,7 +159,7 @@ flutter:
baseVersion: any(named: 'baseVersion'),
artifactPath: any(named: 'artifactPath'),
channel: any(named: 'channel'),
productId: any(named: 'productId'),
appId: any(named: 'appId'),
),
).thenThrow(error);
final tempDir = setUpTempDir();
@@ -173,8 +173,7 @@ flutter:
expect(exitCode, ExitCode.software.code);
});
test('succeeds when publish is successful using existing product id',
() async {
test('succeeds when publish is successful using existing app id', () async {
final tempDir = setUpTempDir();
final artifact = File(p.join(tempDir.path, 'patch.txt'))..createSync();
when(() => argResults.rest).thenReturn([artifact.path]);
@@ -186,7 +185,7 @@ flutter:
verify(
() => codePushClient.createPatch(
baseVersion: version,
productId: productId,
appId: appId,
artifactPath: artifact.path,
channel: 'stable',
),
@@ -26,7 +26,7 @@ Future<void> main() async {
final engine = await client.downloadEngine('latest');
// Create a new Shorebird application.
await client.createApp(productId: '<PRODUCT ID>');
await client.createApp(appId: '<APP ID>');
// List all apps.
final apps = await client.getApps();
@@ -35,7 +35,7 @@ Future<void> main() async {
await client.createPatch(
artifactPath: '<PATH TO ARTIFACT>', // e.g. 'libapp.so'
baseVersion: '<BASE VERSION>', // e.g. '1.0.0'
productId: '<PRODUCT ID>', // e.g. 'shorebird-example'
appId: '<APP ID>', // e.g. 'shorebird-example'
channel: '<CHANNEL>', // e.g. 'stable'
);
@@ -9,7 +9,7 @@ Future<void> main() async {
final engine = await client.downloadEngine('latest');
// Create a new Shorebird application.
await client.createApp(productId: '<PRODUCT ID>');
await client.createApp(appId: '<APP ID>');
// List all apps.
final apps = await client.getApps();
@@ -18,7 +18,7 @@ Future<void> main() async {
await client.createPatch(
artifactPath: '<PATH TO ARTIFACT>', // e.g. 'libapp.so'
baseVersion: '<BASE VERSION>', // e.g. '1.0.0'
productId: '<PRODUCT ID>', // e.g. 'shorebird-example'
appId: '<APP ID>', // e.g. 'shorebird-example'
channel: '<CHANNEL>', // e.g. 'stable'
);
@@ -27,12 +27,12 @@ class CodePushClient {
Map<String, String> get _apiKeyHeader => {'x-api-key': _apiKey};
/// Create a new app with the provided [productId].
Future<void> createApp({required String productId}) async {
/// Create a new app with the provided [appId].
Future<void> createApp({required String appId}) async {
final response = await _httpClient.post(
Uri.parse('$hostedUri/api/v1/apps'),
headers: _apiKeyHeader,
body: json.encode({'product_id': productId}),
body: json.encode({'app_id': appId}),
);
if (response.statusCode != HttpStatus.created) {
@@ -43,7 +43,7 @@ class CodePushClient {
/// Create a new patch.
Future<void> createPatch({
required String baseVersion,
required String productId,
required String appId,
required String channel,
required String artifactPath,
}) async {
@@ -55,7 +55,7 @@ class CodePushClient {
request.files.add(file);
request.fields.addAll({
'base_version': baseVersion,
'product_id': productId,
'app_id': appId,
'channel': channel,
});
request.headers.addAll(_apiKeyHeader);
@@ -66,10 +66,10 @@ class CodePushClient {
}
}
/// Delete the app with the provided [productId].
Future<void> deleteApp({required String productId}) async {
/// Delete the app with the provided [appId].
Future<void> deleteApp({required String appId}) async {
final response = await _httpClient.delete(
Uri.parse('$hostedUri/api/v1/apps/$productId'),
Uri.parse('$hostedUri/api/v1/apps/$appId'),
headers: _apiKeyHeader,
);
@@ -15,7 +15,7 @@ class _FakeBaseRequest extends Fake implements http.BaseRequest {}
void main() {
group('CodePushClient', () {
const apiKey = 'api-key';
const productId = 'shorebird-example';
const appId = 'shorebird-example';
late http.Client httpClient;
late CodePushClient codePushClient;
@@ -48,7 +48,7 @@ void main() {
).thenAnswer((_) async => http.Response('', HttpStatus.badRequest));
expect(
codePushClient.createApp(productId: productId),
codePushClient.createApp(appId: appId),
throwsA(isA<Exception>()),
);
});
@@ -62,7 +62,7 @@ void main() {
),
).thenAnswer((_) async => http.Response('', HttpStatus.created));
await codePushClient.createApp(productId: productId);
await codePushClient.createApp(appId: appId);
final uri = verify(
() => httpClient.post(
@@ -96,7 +96,7 @@ void main() {
codePushClient.createPatch(
artifactPath: fixture.path,
baseVersion: '1.0.0',
productId: 'shorebird-example',
appId: 'shorebird-example',
channel: 'stable',
),
throwsA(isA<Exception>()),
@@ -117,7 +117,7 @@ void main() {
await codePushClient.createPatch(
artifactPath: fixture.path,
baseVersion: '1.0.0',
productId: 'shorebird-example',
appId: 'shorebird-example',
channel: 'stable',
);
@@ -139,7 +139,7 @@ void main() {
).thenAnswer((_) async => http.Response('', HttpStatus.badRequest));
expect(
codePushClient.deleteApp(productId: productId),
codePushClient.deleteApp(appId: appId),
throwsA(isA<Exception>()),
);
});
@@ -152,7 +152,7 @@ void main() {
),
).thenAnswer((_) async => http.Response('', HttpStatus.noContent));
await codePushClient.deleteApp(productId: productId);
await codePushClient.deleteApp(appId: appId);
final uri = verify(
() => httpClient.delete(
@@ -164,7 +164,7 @@ void main() {
expect(
uri,
codePushClient.hostedUri.replace(
path: '/api/v1/apps/$productId',
path: '/api/v1/apps/$appId',
),
);
});
@@ -241,7 +241,7 @@ void main() {
test('completes when request succeeds (populated)', () async {
final expected = [
App(
productId: 'shorebird-example',
appId: 'shorebird-example',
releases: [
Release(
version: '1.0.0',
@@ -276,7 +276,7 @@ void main() {
],
),
App(
productId: 'shorebird-counter',
appId: 'shorebird-counter',
releases: [
Release(
version: '1.0.0',
@@ -9,7 +9,7 @@ part 'app.g.dart';
@JsonSerializable()
class App {
/// {@macro app}
App({required this.productId, List<Release>? releases})
App({required this.appId, List<Release>? releases})
: releases = releases ?? [];
/// Converts a Map<String, dynamic> to an [App]
@@ -18,8 +18,8 @@ class App {
/// Converts a [App] to a Map<String, dynamic>
Map<String, dynamic> toJson() => _$AppToJson(this);
/// The product ID of the app.
final String productId;
/// The ID of the app.
final String appId;
/// List of releases associated with this app.
final List<Release> releases;
@@ -13,7 +13,7 @@ App _$AppFromJson(Map<String, dynamic> json) => $checkedCreate(
json,
($checkedConvert) {
final val = App(
productId: $checkedConvert('product_id', (v) => v as String),
appId: $checkedConvert('app_id', (v) => v as String),
releases: $checkedConvert(
'releases',
(v) => (v as List<dynamic>?)
@@ -22,10 +22,10 @@ App _$AppFromJson(Map<String, dynamic> json) => $checkedCreate(
);
return val;
},
fieldKeyMap: const {'productId': 'product_id'},
fieldKeyMap: const {'appId': 'app_id'},
);
Map<String, dynamic> _$AppToJson(App instance) => <String, dynamic>{
'product_id': instance.productId,
'app_id': instance.appId,
'releases': instance.releases.map((e) => e.toJson()).toList(),
};
@@ -10,7 +10,7 @@ void main() {
apiKey: 'api_key1',
apps: [
App(
productId: 'app1',
appId: 'app1',
releases: [
Release(
version: '1.0.0',
@@ -44,14 +44,14 @@ void main() {
Release(version: '1.0.1'),
],
),
App(productId: 'app2'),
App(appId: 'app2'),
],
),
Account(
apiKey: 'api_key2',
apps: [
App(
productId: 'app2',
appId: 'app2',
releases: [
Release(
version: '1.0.0',
+1 -1
View File
@@ -26,7 +26,7 @@ fn main() {
vm_path: "libflutter.so".to_owned(),
};
let yaml_str = "
product_id: demo
app_id: demo
channel: stable
base_url: http://localhost:8000
";
+4 -4
View File
@@ -12,7 +12,7 @@ class AppParameters extends ffi.Struct {
// ignore: non_constant_identifier_names
external ffi.Pointer<Utf8> client_id;
// ignore: non_constant_identifier_names
external ffi.Pointer<Utf8> product_id;
external ffi.Pointer<Utf8> app_id;
// ignore: non_constant_identifier_names
external ffi.Pointer<Utf8> base_version;
// ignore: non_constant_identifier_names
@@ -26,7 +26,7 @@ class AppParameters extends ffi.Struct {
static ffi.Pointer<AppParameters> allocate(
{required String clientId,
required String productId,
required String appId,
required String version,
required String channel,
required String? updateUrl,
@@ -35,7 +35,7 @@ class AppParameters extends ffi.Struct {
required String cacheDir}) {
var config = calloc<AppParameters>();
config.ref.client_id = clientId.toNativeUtf8();
config.ref.product_id = productId.toNativeUtf8();
config.ref.app_id = appId.toNativeUtf8();
config.ref.base_version = version.toNativeUtf8();
config.ref.channel = channel.toNativeUtf8();
if (updateUrl != null) {
@@ -49,7 +49,7 @@ class AppParameters extends ffi.Struct {
static void free(ffi.Pointer<AppParameters> config) {
calloc.free(config.ref.client_id);
calloc.free(config.ref.product_id);
calloc.free(config.ref.app_id);
calloc.free(config.ref.base_version);
calloc.free(config.ref.channel);
calloc.free(config.ref.update_url);
+2 -2
View File
@@ -51,7 +51,7 @@ class Updater {
// inside a Flutter app.
static void initUpdaterLibrary({
required String clientId,
required String productId,
required String appId,
required String version,
required String channel,
required String? updateUrl,
@@ -60,7 +60,7 @@ class Updater {
required String cacheDir,
}) {
var config = AppParameters.allocate(
productId: productId,
appId: appId,
version: version,
channel: channel,
updateUrl: updateUrl,
+1 -1
View File
@@ -11,7 +11,7 @@ void main(List<String> args) async {
Updater.initUpdaterLibrary(
clientId: 'my-client-id',
productId: 'product',
appId: 'demo',
version: '1.0.0',
channel: 'stable',
updateUrl: null,
+3 -3
View File
@@ -37,7 +37,7 @@ pub struct ResolvedConfig {
is_initialized: bool,
pub cache_dir: String,
pub channel: String,
pub product_id: String,
pub app_id: String,
pub base_version: String,
pub original_libapp_path: String,
pub vm_path: String,
@@ -50,7 +50,7 @@ impl ResolvedConfig {
is_initialized: false,
cache_dir: String::new(),
channel: String::new(),
product_id: String::new(),
app_id: String::new(),
base_version: String::new(),
original_libapp_path: String::new(),
vm_path: String::new(),
@@ -76,7 +76,7 @@ pub fn set_config(config: AppConfig, yaml: YamlConfig) {
.unwrap_or(DEFAULT_CHANNEL)
.to_owned();
lock.cache_dir = config.cache_dir.to_string();
lock.product_id = yaml.product_id.to_string();
lock.app_id = yaml.app_id.to_string();
lock.base_version = config.base_version.to_string();
lock.original_libapp_path = config.original_libapp_path.to_string();
lock.vm_path = config.vm_path.to_string();
+1 -1
View File
@@ -39,7 +39,7 @@ pub fn send_patch_check_request(
let client = reqwest::blocking::Client::new();
let mut body = HashMap::new();
body.insert("client_id", state.client_id());
body.insert("product_id", config.product_id.clone());
body.insert("app_id", config.app_id.clone());
body.insert("channel", config.channel.clone());
body.insert("base_version", config.base_version.clone());
if let Some(patch) = patch {
+2 -2
View File
@@ -3,9 +3,9 @@ use serde::Deserialize;
/// Struct for parsing shorebird.yaml.
#[derive(Deserialize)]
pub struct YamlConfig {
/// Product ID. Required. Generated by Shorebird and included
/// App ID. Required. Generated by Shorebird and included
/// in your app to identify which app/channel/version triple to update.
pub product_id: String,
pub app_id: String,
/// Update channel name. Defaults to "stable" if not set.
pub channel: Option<String>,
/// Update URL. Defaults to the default update URL if not set.