@_nazmiforreal/flutter-ota 0.1.11 → 0.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/bin/flutter-ota-linux-x64 +0 -0
- package/dart-src/packages/cli-tools/.dart_tool/package_config.json +46 -76
- package/dart-src/packages/cli-tools/.dart_tool/package_graph.json +140 -166
- package/dart-src/packages/cli-tools/README.md +1 -1
- package/dart-src/packages/cli-tools/lib/flutter_ota_kit_cli.dart +30 -17
- package/dart-src/packages/cli-tools/lib/src/backend.dart +30 -31
- package/dart-src/packages/cli-tools/lib/src/cli_base.dart +3 -1
- package/dart-src/packages/cli-tools/lib/src/commands/build.dart +44 -43
- package/dart-src/packages/cli-tools/lib/src/commands/bundle.dart +265 -239
- package/dart-src/packages/cli-tools/lib/src/commands/channel.dart +75 -66
- package/dart-src/packages/cli-tools/lib/src/commands/config_command.dart +39 -35
- package/dart-src/packages/cli-tools/lib/src/commands/console.dart +30 -27
- package/dart-src/packages/cli-tools/lib/src/commands/deploy.dart +88 -72
- package/dart-src/packages/cli-tools/lib/src/commands/doctor.dart +66 -29
- package/dart-src/packages/cli-tools/lib/src/commands/fingerprint.dart +10 -6
- package/dart-src/packages/cli-tools/lib/src/commands/init.dart +299 -190
- package/dart-src/packages/cli-tools/lib/src/commands/keys.dart +24 -23
- package/dart-src/packages/cli-tools/lib/src/commands/migrate.dart +111 -97
- package/dart-src/packages/cli-tools/lib/src/commands/pocketbase.dart +237 -0
- package/dart-src/packages/cli-tools/lib/src/commands/rollback.dart +43 -34
- package/dart-src/packages/cli-tools/lib/src/commands/storage.dart +57 -53
- package/dart-src/packages/cli-tools/lib/src/config.dart +227 -93
- package/dart-src/packages/cli-tools/lib/src/operations.dart +9 -8
- package/dart-src/packages/cli-tools/lib/src/pack.dart +26 -25
- package/dart-src/packages/cli-tools/lib/src/pocketbase/data_bootstrap.dart +39 -0
- package/dart-src/packages/cli-tools/lib/src/pocketbase/hooks/bundles.pb.js +56 -0
- package/dart-src/packages/cli-tools/lib/src/pocketbase/installer.dart +189 -0
- package/dart-src/packages/cli-tools/lib/src/pocketbase/process_manager.dart +123 -0
- package/dart-src/packages/cli-tools/lib/src/pocketbase/schema_installer.dart +237 -0
- package/dart-src/packages/cli-tools/lib/src/runner.dart +36 -15
- package/dart-src/packages/cli-tools/lib/src/sign.dart +13 -5
- package/dart-src/packages/cli-tools/lib/src/ui/ui.dart +10 -13
- package/dart-src/packages/cli-tools/lib/src/util.dart +3 -1
- package/dart-src/packages/cli-tools/pubspec.lock +69 -116
- package/dart-src/packages/cli-tools/pubspec.yaml +25 -7
- package/dart-src/packages/cli-tools/test/backends_test.dart +62 -32
- package/dart-src/packages/cli-tools/test/build_pack_test.dart +4 -4
- package/dart-src/packages/cli-tools/test/cli_test.dart +89 -42
- package/dart-src/packages/cli-tools/test/mocks/mock_aws_s3_client.dart +8 -13
- package/dart-src/packages/cli-tools/test/mocks/mock_d1_client.dart +23 -18
- package/dart-src/packages/cli-tools/test/mocks/mock_pocketbase_client.dart +197 -0
- package/dart-src/packages/cli-tools/test/mocks/mock_postgres_client.dart +70 -46
- package/dart-src/packages/cli-tools/test/pocketbase_installer_test.dart +72 -0
- package/dart-src/packages/cli-tools/test/pocketbase_schema_test.dart +107 -0
- package/dart-src/packages/cli-tools/test/pocketbase_smoke_test.dart +59 -0
- package/dart-src/packages/core/README.md +2 -2
- package/dart-src/packages/core/example/lib/main.dart +69 -0
- package/dart-src/packages/core/lib/flutter_ota_kit_core.dart +1 -1
- package/dart-src/packages/core/lib/src/app_update_info.dart +17 -15
- package/dart-src/packages/core/lib/src/bundle.dart +102 -94
- package/dart-src/packages/core/lib/src/bundle_artifacts.dart +1 -2
- package/dart-src/packages/core/lib/src/bundle_patch_artifact.dart +15 -16
- package/dart-src/packages/core/lib/src/changed_asset.dart +24 -22
- package/dart-src/packages/core/lib/src/get_bundles_args.dart +13 -13
- package/dart-src/packages/core/lib/src/metadata.dart +9 -7
- package/dart-src/packages/core/lib/src/patch_info.dart +8 -7
- package/dart-src/packages/core/lib/src/platform.dart +4 -3
- package/dart-src/packages/core/lib/src/rollout.dart +14 -11
- package/dart-src/packages/core/lib/src/semver_range.dart +49 -39
- package/dart-src/packages/core/lib/src/semver_version.dart +8 -7
- package/dart-src/packages/core/lib/src/status.dart +4 -3
- package/dart-src/packages/core/lib/src/update_bundle_params.dart +7 -7
- package/dart-src/packages/core/lib/src/uuid.dart +1 -2
- package/dart-src/packages/core/pubspec.yaml +6 -7
- package/dart-src/packages/core/test/rollout_test.dart +15 -8
- package/dart-src/packages/core/test/semver_test.dart +5 -2
- package/dart-src/packages/core/test/types_test.dart +26 -24
- package/dart-src/packages/core/test/uuid_test.dart +3 -1
- package/dart-src/packages/core/tool/dbg.dart +1 -0
- package/dart-src/plugins/aws/CHANGELOG.md +6 -0
- package/dart-src/plugins/aws/example/lib/main.dart +60 -0
- package/dart-src/plugins/aws/lib/flutter_ota_kit_aws.dart +5 -1
- package/dart-src/plugins/aws/lib/src/aws_cloudfront_client.dart +11 -16
- package/dart-src/plugins/aws/lib/src/aws_cloudfront_signer.dart +7 -2
- package/dart-src/plugins/aws/lib/src/aws_database.dart +14 -18
- package/dart-src/plugins/aws/lib/src/aws_s3_client.dart +23 -18
- package/dart-src/plugins/aws/lib/src/aws_ssm_client.dart +5 -4
- package/dart-src/plugins/aws/lib/src/aws_storage.dart +2 -3
- package/dart-src/plugins/aws/lib/src/aws_storage_profile.dart +10 -16
- package/dart-src/plugins/aws/lib/src/with_cloudfront_signed_url.dart +6 -9
- package/dart-src/plugins/aws/pubspec.yaml +15 -10
- package/dart-src/plugins/aws/test/aws_database_test.dart +51 -57
- package/dart-src/plugins/aws/test/mock_aws_s3_client.dart +8 -13
- package/dart-src/plugins/cloudflare/CHANGELOG.md +7 -0
- package/dart-src/plugins/cloudflare/example/lib/main.dart +62 -0
- package/dart-src/plugins/cloudflare/lib/flutter_ota_kit_cloudflare.dart +4 -2
- package/dart-src/plugins/cloudflare/lib/src/cloudflare_worker_database.dart +3 -3
- package/dart-src/plugins/cloudflare/lib/src/d1_build_where.dart +3 -2
- package/dart-src/plugins/cloudflare/lib/src/d1_bundle_mapper.dart +24 -27
- package/dart-src/plugins/cloudflare/lib/src/d1_database_plugin.dart +22 -30
- package/dart-src/plugins/cloudflare/lib/src/r2_config.dart +1 -1
- package/dart-src/plugins/cloudflare/lib/src/r2_s3_client.dart +21 -29
- package/dart-src/plugins/cloudflare/lib/src/r2_storage.dart +7 -7
- package/dart-src/plugins/cloudflare/lib/src/r2_storage_profile.dart +7 -15
- package/dart-src/plugins/cloudflare/pubspec.yaml +14 -9
- package/dart-src/plugins/cloudflare/test/cloudflare_worker_database_test.dart +46 -42
- package/dart-src/plugins/cloudflare/test/d1_database_test.dart +100 -90
- package/dart-src/plugins/cloudflare/test/mock_d1_client.dart +23 -18
- package/dart-src/plugins/cloudflare/test/mock_r2_client.dart +8 -13
- package/dart-src/plugins/cloudflare/test/r2_storage_test.dart +1 -4
- package/dart-src/plugins/plugin-core/CHANGELOG.md +16 -0
- package/dart-src/plugins/plugin-core/example/lib/main.dart +61 -0
- package/dart-src/plugins/plugin-core/lib/flutter_ota_kit_plugin_core.dart +3 -7
- package/dart-src/plugins/plugin-core/lib/src/asset_storage_layout.dart +5 -5
- package/dart-src/plugins/plugin-core/lib/src/bundle_helpers.dart +23 -0
- package/dart-src/plugins/plugin-core/lib/src/bundle_storage_layout.dart +16 -10
- package/dart-src/plugins/plugin-core/lib/src/bundle_unit_of_work.dart +31 -26
- package/dart-src/plugins/plugin-core/lib/src/calculate_pagination.dart +5 -1
- package/dart-src/plugins/plugin-core/lib/src/content_addressed_assets.dart +1 -1
- package/dart-src/plugins/plugin-core/lib/src/create_blob_database_plugin.dart +78 -71
- package/dart-src/plugins/plugin-core/lib/src/create_database_plugin.dart +56 -35
- package/dart-src/plugins/plugin-core/lib/src/create_storage_plugin.dart +10 -13
- package/dart-src/plugins/plugin-core/lib/src/paginate_bundles.dart +30 -17
- package/dart-src/plugins/plugin-core/lib/src/parse_storage_uri.dart +3 -1
- package/dart-src/plugins/plugin-core/lib/src/query_bundles.dart +5 -3
- package/dart-src/plugins/plugin-core/lib/src/request_update_bundle_state.dart +2 -4
- package/dart-src/plugins/plugin-core/lib/src/storage_helpers.dart +18 -0
- package/dart-src/plugins/plugin-core/lib/src/types.dart +7 -6
- package/dart-src/plugins/plugin-core/pubspec.yaml +12 -9
- package/dart-src/plugins/plugin-core/test/asset_storage_layout_test.dart +13 -9
- package/dart-src/plugins/plugin-core/test/bundle_unit_of_work_test.dart +28 -15
- package/dart-src/plugins/plugin-core/test/create_blob_database_plugin_test.dart +254 -122
- package/dart-src/plugins/plugin-core/test/create_database_plugin_test.dart +36 -32
- package/dart-src/plugins/plugin-core/test/create_storage_plugin_test.dart +18 -15
- package/dart-src/plugins/plugin-core/test/generate_min_bundle_id_test.dart +8 -3
- package/dart-src/plugins/plugin-core/test/get_update_info_test.dart +682 -693
- package/dart-src/plugins/plugin-core/test/helpers_test.dart +45 -21
- package/dart-src/plugins/plugin-core/test/query_bundles_test.dart +76 -13
- package/dart-src/plugins/plugin-core/test/uuidv7_test.dart +20 -9
- package/dart-src/plugins/pocketbase/CHANGELOG.md +8 -0
- package/dart-src/plugins/pocketbase/LICENSE +21 -0
- package/dart-src/plugins/pocketbase/README.md +54 -0
- package/dart-src/plugins/pocketbase/example/lib/main.dart +62 -0
- package/dart-src/plugins/pocketbase/lib/flutter_ota_kit_pocketbase.dart +28 -0
- package/dart-src/plugins/pocketbase/lib/src/pocketbase_bundle_mapper.dart +121 -0
- package/dart-src/plugins/pocketbase/lib/src/pocketbase_client.dart +349 -0
- package/dart-src/plugins/pocketbase/lib/src/pocketbase_config.dart +61 -0
- package/dart-src/plugins/pocketbase/lib/src/pocketbase_database.dart +278 -0
- package/dart-src/plugins/pocketbase/lib/src/pocketbase_storage.dart +255 -0
- package/dart-src/plugins/pocketbase/pubspec.yaml +26 -0
- package/dart-src/plugins/pocketbase/test/pb_uri_test.dart +12 -0
- package/dart-src/plugins/postgres/CHANGELOG.md +6 -0
- package/dart-src/plugins/postgres/example/lib/main.dart +67 -0
- package/dart-src/plugins/postgres/lib/flutter_ota_kit_postgres.dart +3 -6
- package/dart-src/plugins/postgres/lib/src/postgres_bundle_mapper.dart +32 -52
- package/dart-src/plugins/postgres/lib/src/postgres_config.dart +3 -1
- package/dart-src/plugins/postgres/lib/src/postgres_database.dart +28 -38
- package/dart-src/plugins/postgres/lib/src/postgres_get_update_info.dart +16 -14
- package/dart-src/plugins/postgres/lib/src/postgres_storage.dart +26 -14
- package/dart-src/plugins/postgres/lib/src/postgres_types.dart +27 -28
- package/dart-src/plugins/postgres/pubspec.yaml +14 -9
- package/dart-src/plugins/postgres/test/mock_postgres_client.dart +62 -39
- package/dart-src/plugins/postgres/test/postgres_bundle_mapper_test.dart +3 -4
- package/dart-src/plugins/postgres/test/postgres_database_test.dart +102 -73
- package/dart-src/plugins/postgres/test/postgres_storage_runtime_test.dart +60 -0
- package/dart-src/plugins/supabase/CHANGELOG.md +17 -0
- package/dart-src/plugins/supabase/README.md +2 -2
- package/dart-src/plugins/supabase/example/lib/main.dart +63 -0
- package/dart-src/plugins/supabase/lib/flutter_ota_kit_supabase.dart +2 -0
- package/dart-src/plugins/supabase/lib/src/error_message.dart +11 -0
- package/dart-src/plugins/supabase/lib/src/supabase_bundle_mapper.dart +34 -58
- package/dart-src/plugins/supabase/lib/src/supabase_client_adapter.dart +3 -13
- package/dart-src/plugins/supabase/lib/src/supabase_client_http.dart +34 -52
- package/dart-src/plugins/supabase/lib/src/supabase_database.dart +38 -30
- package/dart-src/plugins/supabase/lib/src/supabase_edge_function_storage.dart +21 -29
- package/dart-src/plugins/supabase/lib/src/supabase_signed_url_batcher.dart +7 -19
- package/dart-src/plugins/supabase/lib/src/supabase_storage.dart +18 -29
- package/dart-src/plugins/supabase/lib/src/types.dart +26 -26
- package/dart-src/plugins/supabase/pubspec.yaml +14 -9
- package/dart-src/plugins/supabase/test/mock_supabase_client.dart +57 -57
- package/dart-src/plugins/supabase/test/supabase_bundle_mapper_test.dart +30 -27
- package/dart-src/plugins/supabase/test/supabase_database_test.dart +26 -35
- package/dart-src/plugins/supabase/test/supabase_storage_test.dart +27 -34
- package/package.json +2 -2
- package/scripts/vendor.sh +1 -1
|
@@ -7,8 +7,12 @@ import '../ui/ui.dart';
|
|
|
7
7
|
/// directly from the CLI (no need to open the provider dashboard).
|
|
8
8
|
class StorageCommand extends FlutterPatcherCommand {
|
|
9
9
|
StorageCommand({this.config, this.backendOverride}) {
|
|
10
|
-
addSubcommand(
|
|
11
|
-
|
|
10
|
+
addSubcommand(
|
|
11
|
+
StorageListCommand(config: config, backendOverride: backendOverride),
|
|
12
|
+
);
|
|
13
|
+
addSubcommand(
|
|
14
|
+
StorageDeleteCommand(config: config, backendOverride: backendOverride),
|
|
15
|
+
);
|
|
12
16
|
}
|
|
13
17
|
|
|
14
18
|
final FlutterPatcherConfig? config;
|
|
@@ -41,31 +45,31 @@ class StorageListCommand extends FlutterPatcherCommand {
|
|
|
41
45
|
|
|
42
46
|
@override
|
|
43
47
|
Future<int> run() => runGuarded(() async {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
48
|
+
final cfg = effectiveConfig(config ?? loadConfig(), argResults!);
|
|
49
|
+
final backend = requireBackend(cfg, override: backendOverride);
|
|
50
|
+
final prefix = argResults!['prefix'] as String?;
|
|
51
|
+
banner('storage · list');
|
|
52
|
+
final objects = await backend.storage.listObjects(
|
|
53
|
+
prefix == null || prefix.isEmpty ? null : prefix,
|
|
54
|
+
);
|
|
55
|
+
if (objects.isEmpty) {
|
|
56
|
+
step('(no objects)');
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
final lines = <String>[];
|
|
60
|
+
for (final o in objects) {
|
|
61
|
+
final size = o.size >= 1024 * 1024
|
|
62
|
+
? '${(o.size / (1024 * 1024)).toStringAsFixed(2)} MB'
|
|
63
|
+
: o.size >= 1024
|
|
64
|
+
? '${(o.size / 1024).toStringAsFixed(1)} KB'
|
|
65
|
+
: '${o.size} B';
|
|
66
|
+
lines
|
|
67
|
+
..add(kv('key', cyan(o.key)))
|
|
68
|
+
..add(kv('size', size))
|
|
69
|
+
..add('');
|
|
70
|
+
}
|
|
71
|
+
box('${objects.length} objects', lines);
|
|
72
|
+
});
|
|
69
73
|
}
|
|
70
74
|
|
|
71
75
|
class StorageDeleteCommand extends FlutterPatcherCommand {
|
|
@@ -88,30 +92,30 @@ class StorageDeleteCommand extends FlutterPatcherCommand {
|
|
|
88
92
|
|
|
89
93
|
@override
|
|
90
94
|
Future<int> run() => runGuarded(() async {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
95
|
+
final keys = (argResults!['key'] as List<String>?) ?? <String>[];
|
|
96
|
+
final uri = argResults!['uri'] as String?;
|
|
97
|
+
if (keys.isEmpty && (uri == null || uri.isEmpty)) {
|
|
98
|
+
throw PackException(
|
|
99
|
+
'Usage: flutter-ota storage delete --key <key> [--key <key>...] '
|
|
100
|
+
'| --uri <storageUri>',
|
|
101
|
+
64,
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
final cfg = effectiveConfig(config ?? loadConfig(), argResults!);
|
|
105
|
+
final backend = requireBackend(cfg, override: backendOverride);
|
|
106
|
+
banner('storage · delete');
|
|
107
|
+
if (keys.isNotEmpty) {
|
|
108
|
+
await spinner(
|
|
109
|
+
() => backend.storage.deleteObjects(keys),
|
|
110
|
+
'Deleting ${keys.length} object(s)',
|
|
111
|
+
done: 'Deleted',
|
|
112
|
+
);
|
|
113
|
+
} else {
|
|
114
|
+
await spinner(
|
|
115
|
+
() => backend.storage.delete(uri!),
|
|
116
|
+
'Deleting $uri',
|
|
117
|
+
done: 'Deleted',
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
});
|
|
117
121
|
}
|
|
@@ -4,6 +4,7 @@ import 'dart:io';
|
|
|
4
4
|
import 'package:flutter_ota_kit_aws/flutter_ota_kit_aws.dart';
|
|
5
5
|
import 'package:postgres/postgres.dart';
|
|
6
6
|
import 'package:flutter_ota_kit_cloudflare/flutter_ota_kit_cloudflare.dart';
|
|
7
|
+
import 'package:flutter_ota_kit_pocketbase/flutter_ota_kit_pocketbase.dart';
|
|
7
8
|
import 'package:flutter_ota_kit_postgres/flutter_ota_kit_postgres.dart';
|
|
8
9
|
|
|
9
10
|
import 'package:flutter_ota_kit_supabase/flutter_ota_kit_supabase.dart';
|
|
@@ -22,6 +23,7 @@ class FlutterPatcherConfig {
|
|
|
22
23
|
this.postgres = const PostgresConfigJson(),
|
|
23
24
|
this.cloudflare = const CloudflareConfigJson(),
|
|
24
25
|
this.aws = const AwsConfigJson(),
|
|
26
|
+
this.pocketbase = const PocketBaseConfigJson(),
|
|
25
27
|
this.channel = 'production',
|
|
26
28
|
this.platform = 'android',
|
|
27
29
|
this.source = './dist',
|
|
@@ -43,6 +45,9 @@ class FlutterPatcherConfig {
|
|
|
43
45
|
aws: AwsConfigJson.fromJson(
|
|
44
46
|
(json['aws'] as Map?)?.cast<String, dynamic>() ?? {},
|
|
45
47
|
),
|
|
48
|
+
pocketbase: PocketBaseConfigJson.fromJson(
|
|
49
|
+
(json['pocketbase'] as Map?)?.cast<String, dynamic>() ?? {},
|
|
50
|
+
),
|
|
46
51
|
channel: json['channel'] as String? ?? 'production',
|
|
47
52
|
platform: json['platform'] as String? ?? 'android',
|
|
48
53
|
source: json['source'] as String? ?? './dist',
|
|
@@ -54,22 +59,24 @@ class FlutterPatcherConfig {
|
|
|
54
59
|
final PostgresConfigJson postgres;
|
|
55
60
|
final CloudflareConfigJson cloudflare;
|
|
56
61
|
final AwsConfigJson aws;
|
|
62
|
+
final PocketBaseConfigJson pocketbase;
|
|
57
63
|
final String channel;
|
|
58
64
|
final String platform;
|
|
59
65
|
final String source;
|
|
60
66
|
final String? publicKey;
|
|
61
67
|
|
|
62
68
|
Map<String, dynamic> toJson() => {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
69
|
+
'provider': provider,
|
|
70
|
+
'supabase': supabase.toJson(),
|
|
71
|
+
'postgres': postgres.toJson(),
|
|
72
|
+
'cloudflare': cloudflare.toJson(),
|
|
73
|
+
'aws': aws.toJson(),
|
|
74
|
+
'pocketbase': pocketbase.toJson(),
|
|
75
|
+
'channel': channel,
|
|
76
|
+
'platform': platform,
|
|
77
|
+
'source': source,
|
|
78
|
+
if (publicKey != null) 'publicKey': publicKey,
|
|
79
|
+
};
|
|
73
80
|
|
|
74
81
|
FlutterPatcherConfig copyWith({
|
|
75
82
|
String? provider,
|
|
@@ -77,22 +84,23 @@ class FlutterPatcherConfig {
|
|
|
77
84
|
PostgresConfigJson? postgres,
|
|
78
85
|
CloudflareConfigJson? cloudflare,
|
|
79
86
|
AwsConfigJson? aws,
|
|
87
|
+
PocketBaseConfigJson? pocketbase,
|
|
80
88
|
String? channel,
|
|
81
89
|
String? platform,
|
|
82
90
|
String? source,
|
|
83
91
|
String? publicKey,
|
|
84
|
-
}) =>
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
92
|
+
}) => FlutterPatcherConfig(
|
|
93
|
+
provider: provider ?? this.provider,
|
|
94
|
+
supabase: supabase ?? this.supabase,
|
|
95
|
+
postgres: postgres ?? this.postgres,
|
|
96
|
+
cloudflare: cloudflare ?? this.cloudflare,
|
|
97
|
+
aws: aws ?? this.aws,
|
|
98
|
+
pocketbase: pocketbase ?? this.pocketbase,
|
|
99
|
+
channel: channel ?? this.channel,
|
|
100
|
+
platform: platform ?? this.platform,
|
|
101
|
+
source: source ?? this.source,
|
|
102
|
+
publicKey: publicKey ?? this.publicKey,
|
|
103
|
+
);
|
|
96
104
|
}
|
|
97
105
|
|
|
98
106
|
/// Supabase section of [FlutterPatcherConfig].
|
|
@@ -127,24 +135,25 @@ class SupabaseConfigJson {
|
|
|
127
135
|
final String? databaseUrl;
|
|
128
136
|
|
|
129
137
|
Map<String, dynamic> toJson() => {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
+
if (url != null) 'url': url,
|
|
139
|
+
if (serviceRoleKey != null) 'serviceRoleKey': serviceRoleKey,
|
|
140
|
+
if (anonKey != null) 'anonKey': anonKey,
|
|
141
|
+
if (bucket != null) 'bucket': bucket,
|
|
142
|
+
if (basePath != null) 'basePath': basePath,
|
|
143
|
+
if (managementKey != null) 'managementKey': managementKey,
|
|
144
|
+
if (databaseUrl != null) 'databaseUrl': databaseUrl,
|
|
145
|
+
};
|
|
138
146
|
}
|
|
139
147
|
|
|
140
148
|
/// Search order for a config file on disk. Both the project config and the
|
|
141
149
|
/// global config live under a `.flutter_ota_kit/` directory so all CLI state is
|
|
142
150
|
/// grouped in one place (and can be git-ignored together).
|
|
143
151
|
List<File> configCandidates() {
|
|
144
|
-
final cwd = File(
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
152
|
+
final cwd = File(
|
|
153
|
+
p.join(Directory.current.path, '.flutter_ota_kit', 'config.json'),
|
|
154
|
+
);
|
|
155
|
+
final home =
|
|
156
|
+
Platform.environment['HOME'] ?? Platform.environment['USERPROFILE'] ?? '';
|
|
148
157
|
final global = File(p.join(home, '.flutter_ota_kit', 'config.json'));
|
|
149
158
|
return [cwd, global];
|
|
150
159
|
}
|
|
@@ -222,7 +231,8 @@ SupabaseServiceRoleConfig resolveSupabaseConfig(
|
|
|
222
231
|
}) {
|
|
223
232
|
final env = Platform.environment;
|
|
224
233
|
final resolvedUrl = url ?? env['SUPABASE_URL'] ?? config.supabase.url;
|
|
225
|
-
final resolvedService =
|
|
234
|
+
final resolvedService =
|
|
235
|
+
serviceRoleKey ??
|
|
226
236
|
env['SUPABASE_SERVICE_ROLE_KEY'] ??
|
|
227
237
|
config.supabase.serviceRoleKey;
|
|
228
238
|
final resolvedAnon =
|
|
@@ -269,11 +279,12 @@ SupabaseStorageConfig resolveSupabaseStorageConfig(
|
|
|
269
279
|
clientFactory: db.clientFactory,
|
|
270
280
|
bucketName: db.supabaseServiceRoleKey != null || db.supabaseAnonKey != null
|
|
271
281
|
? (bucket ??
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
282
|
+
Platform.environment['SUPABASE_BUCKET'] ??
|
|
283
|
+
config.supabase.bucket ??
|
|
284
|
+
'bundles')
|
|
275
285
|
: (bucket ?? config.supabase.bucket ?? 'bundles'),
|
|
276
|
-
basePath:
|
|
286
|
+
basePath:
|
|
287
|
+
basePath ??
|
|
277
288
|
Platform.environment['SUPABASE_BASE_PATH'] ??
|
|
278
289
|
config.supabase.basePath,
|
|
279
290
|
);
|
|
@@ -318,15 +329,15 @@ class PostgresConfigJson {
|
|
|
318
329
|
final String? servingBaseUrl;
|
|
319
330
|
|
|
320
331
|
Map<String, dynamic> toJson() => {
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
332
|
+
if (host != null) 'host': host,
|
|
333
|
+
if (port != null) 'port': port,
|
|
334
|
+
if (database != null) 'database': database,
|
|
335
|
+
if (username != null) 'username': username,
|
|
336
|
+
if (password != null) 'password': password,
|
|
337
|
+
if (sslMode != null) 'sslMode': sslMode,
|
|
338
|
+
if (basePath != null) 'basePath': basePath,
|
|
339
|
+
if (servingBaseUrl != null) 'servingBaseUrl': servingBaseUrl,
|
|
340
|
+
};
|
|
330
341
|
}
|
|
331
342
|
|
|
332
343
|
SslMode? _parseSslMode(String? value) {
|
|
@@ -358,13 +369,12 @@ PostgresConfig resolvePostgresDatabaseConfig(
|
|
|
358
369
|
final resolvedHost = host ?? env['POSTGRES_HOST'] ?? config.postgres.host;
|
|
359
370
|
final resolvedDatabase =
|
|
360
371
|
database ?? env['POSTGRES_DB'] ?? config.postgres.database;
|
|
361
|
-
final resolvedUser =
|
|
372
|
+
final resolvedUser =
|
|
373
|
+
username ?? env['POSTGRES_USER'] ?? config.postgres.username;
|
|
362
374
|
final resolvedPassword =
|
|
363
375
|
password ?? env['POSTGRES_PASSWORD'] ?? config.postgres.password;
|
|
364
|
-
final resolvedPort =
|
|
365
|
-
env['POSTGRES_PORT'] ??
|
|
366
|
-
config.postgres.port ??
|
|
367
|
-
'5432';
|
|
376
|
+
final resolvedPort =
|
|
377
|
+
port ?? env['POSTGRES_PORT'] ?? config.postgres.port ?? '5432';
|
|
368
378
|
final resolvedSsl =
|
|
369
379
|
sslMode ?? env['POSTGRES_SSLMODE'] ?? config.postgres.sslMode;
|
|
370
380
|
|
|
@@ -411,10 +421,12 @@ PostgresStorageConfig resolvePostgresStorageConfig(
|
|
|
411
421
|
);
|
|
412
422
|
return PostgresStorageConfig(
|
|
413
423
|
db: db,
|
|
414
|
-
basePath:
|
|
424
|
+
basePath:
|
|
425
|
+
basePath ??
|
|
415
426
|
Platform.environment['POSTGRES_BASE_PATH'] ??
|
|
416
427
|
config.postgres.basePath,
|
|
417
|
-
servingBaseUrl:
|
|
428
|
+
servingBaseUrl:
|
|
429
|
+
servingBaseUrl ??
|
|
418
430
|
Platform.environment['POSTGRES_SERVING_BASE_URL'] ??
|
|
419
431
|
config.postgres.servingBaseUrl,
|
|
420
432
|
);
|
|
@@ -456,14 +468,14 @@ class CloudflareConfigJson {
|
|
|
456
468
|
final String? r2BasePath;
|
|
457
469
|
|
|
458
470
|
Map<String, dynamic> toJson() => {
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
471
|
+
if (accountId != null) 'accountId': accountId,
|
|
472
|
+
if (d1DatabaseId != null) 'd1DatabaseId': d1DatabaseId,
|
|
473
|
+
if (apiToken != null) 'apiToken': apiToken,
|
|
474
|
+
if (r2Bucket != null) 'r2Bucket': r2Bucket,
|
|
475
|
+
if (r2AccessKeyId != null) 'r2AccessKeyId': r2AccessKeyId,
|
|
476
|
+
if (r2SecretAccessKey != null) 'r2SecretAccessKey': r2SecretAccessKey,
|
|
477
|
+
if (r2BasePath != null) 'r2BasePath': r2BasePath,
|
|
478
|
+
};
|
|
467
479
|
}
|
|
468
480
|
|
|
469
481
|
/// Resolve the Cloudflare D1 database config.
|
|
@@ -477,15 +489,14 @@ D1DatabaseConfig resolveCloudflareDatabaseConfig(
|
|
|
477
489
|
final env = Platform.environment;
|
|
478
490
|
final resolvedAccount =
|
|
479
491
|
accountId ?? env['CLOUDFLARE_ACCOUNT_ID'] ?? config.cloudflare.accountId;
|
|
480
|
-
final resolvedDb =
|
|
492
|
+
final resolvedDb =
|
|
493
|
+
d1DatabaseId ??
|
|
481
494
|
env['CLOUDFLARE_D1_DATABASE_ID'] ??
|
|
482
495
|
config.cloudflare.d1DatabaseId;
|
|
483
496
|
final resolvedToken =
|
|
484
497
|
apiToken ?? env['CLOUDFLARE_API_TOKEN'] ?? config.cloudflare.apiToken;
|
|
485
498
|
|
|
486
|
-
if (resolvedAccount == null ||
|
|
487
|
-
resolvedDb == null ||
|
|
488
|
-
resolvedToken == null) {
|
|
499
|
+
if (resolvedAccount == null || resolvedDb == null || resolvedToken == null) {
|
|
489
500
|
throw StateError(
|
|
490
501
|
'Cloudflare requires accountId, d1DatabaseId and apiToken. Set them via '
|
|
491
502
|
'flags, CLOUDFLARE_* env vars, or `flutter_ota_kit config set cloudflare.*`.',
|
|
@@ -511,16 +522,17 @@ R2S3StorageConfig resolveCloudflareStorageConfig(
|
|
|
511
522
|
R2S3ClientFactory? clientFactory,
|
|
512
523
|
}) {
|
|
513
524
|
final env = Platform.environment;
|
|
514
|
-
final resolvedAccount =
|
|
525
|
+
final resolvedAccount =
|
|
526
|
+
accountId ??
|
|
515
527
|
env['CLOUDFLARE_ACCOUNT_ID'] ??
|
|
516
528
|
env['R2_ACCOUNT_ID'] ??
|
|
517
529
|
config.cloudflare.accountId;
|
|
518
530
|
final resolvedBucket =
|
|
519
531
|
bucket ?? env['R2_BUCKET'] ?? config.cloudflare.r2Bucket ?? 'bundles';
|
|
520
|
-
final resolvedKey =
|
|
521
|
-
env['R2_ACCESS_KEY_ID'] ??
|
|
522
|
-
|
|
523
|
-
|
|
532
|
+
final resolvedKey =
|
|
533
|
+
accessKeyId ?? env['R2_ACCESS_KEY_ID'] ?? config.cloudflare.r2AccessKeyId;
|
|
534
|
+
final resolvedSecret =
|
|
535
|
+
secretAccessKey ??
|
|
524
536
|
env['R2_SECRET_ACCESS_KEY'] ??
|
|
525
537
|
config.cloudflare.r2SecretAccessKey;
|
|
526
538
|
|
|
@@ -560,14 +572,14 @@ class AwsConfigJson {
|
|
|
560
572
|
});
|
|
561
573
|
|
|
562
574
|
factory AwsConfigJson.fromJson(Map<String, dynamic> json) => AwsConfigJson(
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
575
|
+
bucket: json['bucket'] as String?,
|
|
576
|
+
region: json['region'] as String?,
|
|
577
|
+
accessKeyId: json['accessKeyId'] as String?,
|
|
578
|
+
secretAccessKey: json['secretAccessKey'] as String?,
|
|
579
|
+
endpoint: json['endpoint'] as String?,
|
|
580
|
+
basePath: json['basePath'] as String?,
|
|
581
|
+
sessionToken: json['sessionToken'] as String?,
|
|
582
|
+
);
|
|
571
583
|
|
|
572
584
|
final String? bucket;
|
|
573
585
|
final String? region;
|
|
@@ -578,14 +590,14 @@ class AwsConfigJson {
|
|
|
578
590
|
final String? sessionToken;
|
|
579
591
|
|
|
580
592
|
Map<String, dynamic> toJson() => {
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
593
|
+
if (bucket != null) 'bucket': bucket,
|
|
594
|
+
if (region != null) 'region': region,
|
|
595
|
+
if (accessKeyId != null) 'accessKeyId': accessKeyId,
|
|
596
|
+
if (secretAccessKey != null) 'secretAccessKey': secretAccessKey,
|
|
597
|
+
if (endpoint != null) 'endpoint': endpoint,
|
|
598
|
+
if (basePath != null) 'basePath': basePath,
|
|
599
|
+
if (sessionToken != null) 'sessionToken': sessionToken,
|
|
600
|
+
};
|
|
589
601
|
}
|
|
590
602
|
|
|
591
603
|
/// Resolve the AWS S3 database config.
|
|
@@ -599,7 +611,8 @@ S3DatabaseConfig resolveAwsDatabaseConfig(
|
|
|
599
611
|
String? endpoint,
|
|
600
612
|
String? sessionToken,
|
|
601
613
|
AwsS3ClientLike Function(S3DatabaseConfig config)? clientFactory,
|
|
602
|
-
AwsCloudFrontClientLike Function(S3DatabaseConfig config)?
|
|
614
|
+
AwsCloudFrontClientLike Function(S3DatabaseConfig config)?
|
|
615
|
+
cloudfrontClientFactory,
|
|
603
616
|
}) {
|
|
604
617
|
final env = Platform.environment;
|
|
605
618
|
final resolvedBucket = bucket ?? env['AWS_BUCKET'] ?? config.aws.bucket;
|
|
@@ -607,7 +620,9 @@ S3DatabaseConfig resolveAwsDatabaseConfig(
|
|
|
607
620
|
final resolvedKey =
|
|
608
621
|
accessKeyId ?? env['AWS_ACCESS_KEY_ID'] ?? config.aws.accessKeyId;
|
|
609
622
|
final resolvedSecret =
|
|
610
|
-
secretAccessKey ??
|
|
623
|
+
secretAccessKey ??
|
|
624
|
+
env['AWS_SECRET_ACCESS_KEY'] ??
|
|
625
|
+
config.aws.secretAccessKey;
|
|
611
626
|
|
|
612
627
|
if (resolvedBucket == null ||
|
|
613
628
|
resolvedRegion == null ||
|
|
@@ -626,7 +641,8 @@ S3DatabaseConfig resolveAwsDatabaseConfig(
|
|
|
626
641
|
secretAccessKey: resolvedSecret,
|
|
627
642
|
basePath: basePath ?? env['AWS_BASE_PATH'] ?? config.aws.basePath,
|
|
628
643
|
endpoint: endpoint ?? env['AWS_ENDPOINT'] ?? config.aws.endpoint,
|
|
629
|
-
sessionToken:
|
|
644
|
+
sessionToken:
|
|
645
|
+
sessionToken ?? env['AWS_SESSION_TOKEN'] ?? config.aws.sessionToken,
|
|
630
646
|
clientFactory: clientFactory ?? defaultAwsS3DatabaseClientFactory,
|
|
631
647
|
cloudfrontClientFactory:
|
|
632
648
|
cloudfrontClientFactory ?? defaultAwsCloudFrontClientFactory,
|
|
@@ -651,7 +667,9 @@ AwsS3StorageConfig resolveAwsStorageConfig(
|
|
|
651
667
|
final resolvedKey =
|
|
652
668
|
accessKeyId ?? env['AWS_ACCESS_KEY_ID'] ?? config.aws.accessKeyId;
|
|
653
669
|
final resolvedSecret =
|
|
654
|
-
secretAccessKey ??
|
|
670
|
+
secretAccessKey ??
|
|
671
|
+
env['AWS_SECRET_ACCESS_KEY'] ??
|
|
672
|
+
config.aws.secretAccessKey;
|
|
655
673
|
|
|
656
674
|
if (resolvedBucket == null ||
|
|
657
675
|
resolvedRegion == null ||
|
|
@@ -670,7 +688,123 @@ AwsS3StorageConfig resolveAwsStorageConfig(
|
|
|
670
688
|
secretAccessKey: resolvedSecret,
|
|
671
689
|
basePath: basePath ?? env['AWS_BASE_PATH'] ?? config.aws.basePath,
|
|
672
690
|
endpoint: endpoint ?? env['AWS_ENDPOINT'] ?? config.aws.endpoint,
|
|
673
|
-
sessionToken:
|
|
691
|
+
sessionToken:
|
|
692
|
+
sessionToken ?? env['AWS_SESSION_TOKEN'] ?? config.aws.sessionToken,
|
|
674
693
|
clientFactory: clientFactory ?? defaultAwsS3ClientFactory,
|
|
675
694
|
);
|
|
676
695
|
}
|
|
696
|
+
|
|
697
|
+
// ---------------------------------------------------------------------------
|
|
698
|
+
// PocketBase backend config
|
|
699
|
+
// ---------------------------------------------------------------------------
|
|
700
|
+
|
|
701
|
+
/// PocketBase section of [FlutterPatcherConfig].
|
|
702
|
+
class PocketBaseConfigJson {
|
|
703
|
+
const PocketBaseConfigJson({
|
|
704
|
+
this.url,
|
|
705
|
+
this.adminEmail,
|
|
706
|
+
this.adminPassword,
|
|
707
|
+
this.bundlesCollection = 'bundles',
|
|
708
|
+
this.channelsCollection = 'channels',
|
|
709
|
+
this.bundlesBucket = 'bundles',
|
|
710
|
+
});
|
|
711
|
+
|
|
712
|
+
factory PocketBaseConfigJson.fromJson(Map<String, dynamic> json) =>
|
|
713
|
+
PocketBaseConfigJson(
|
|
714
|
+
url: json['url'] as String?,
|
|
715
|
+
adminEmail: json['adminEmail'] as String?,
|
|
716
|
+
adminPassword: json['adminPassword'] as String?,
|
|
717
|
+
bundlesCollection: (json['bundlesCollection'] as String?) ?? 'bundles',
|
|
718
|
+
channelsCollection:
|
|
719
|
+
(json['channelsCollection'] as String?) ?? 'channels',
|
|
720
|
+
bundlesBucket: (json['bundlesBucket'] as String?) ?? 'bundles',
|
|
721
|
+
);
|
|
722
|
+
|
|
723
|
+
final String? url;
|
|
724
|
+
final String? adminEmail;
|
|
725
|
+
final String? adminPassword;
|
|
726
|
+
final String bundlesCollection;
|
|
727
|
+
final String channelsCollection;
|
|
728
|
+
final String bundlesBucket;
|
|
729
|
+
|
|
730
|
+
Map<String, dynamic> toJson() => {
|
|
731
|
+
if (url != null) 'url': url,
|
|
732
|
+
if (adminEmail != null) 'adminEmail': adminEmail,
|
|
733
|
+
if (adminPassword != null) 'adminPassword': adminPassword,
|
|
734
|
+
'bundlesCollection': bundlesCollection,
|
|
735
|
+
'channelsCollection': channelsCollection,
|
|
736
|
+
'bundlesBucket': bundlesBucket,
|
|
737
|
+
};
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
/// Resolve the PocketBase database config (flag > env > json precedence).
|
|
741
|
+
PocketBaseDatabaseConfig resolvePocketBaseDatabaseConfig(
|
|
742
|
+
FlutterPatcherConfig config, {
|
|
743
|
+
String? url,
|
|
744
|
+
String? adminEmail,
|
|
745
|
+
String? adminPassword,
|
|
746
|
+
PocketBaseClientFactory? clientFactory,
|
|
747
|
+
}) {
|
|
748
|
+
final env = Platform.environment;
|
|
749
|
+
final resolvedUrl = url ?? env['POCKETBASE_URL'] ?? config.pocketbase.url;
|
|
750
|
+
final resolvedEmail =
|
|
751
|
+
adminEmail ??
|
|
752
|
+
env['POCKETBASE_ADMIN_EMAIL'] ??
|
|
753
|
+
config.pocketbase.adminEmail;
|
|
754
|
+
final resolvedPassword =
|
|
755
|
+
adminPassword ??
|
|
756
|
+
env['POCKETBASE_ADMIN_PASSWORD'] ??
|
|
757
|
+
config.pocketbase.adminPassword;
|
|
758
|
+
|
|
759
|
+
if (resolvedUrl == null || resolvedUrl.isEmpty) {
|
|
760
|
+
throw StateError(
|
|
761
|
+
'PocketBase URL is required. Set --pb-url, POCKETBASE_URL, or '
|
|
762
|
+
'`flutter_ota_kit config set pocketbase.url <url>`.',
|
|
763
|
+
);
|
|
764
|
+
}
|
|
765
|
+
if (resolvedEmail == null || resolvedPassword == null) {
|
|
766
|
+
throw StateError(
|
|
767
|
+
'PocketBase admin credentials are required. Set --pb-email, '
|
|
768
|
+
'--pb-password, POCKETBASE_ADMIN_EMAIL/PASSWORD, or '
|
|
769
|
+
'`flutter_ota_kit config set pocketbase.*`.',
|
|
770
|
+
);
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
return PocketBaseDatabaseConfig(
|
|
774
|
+
url: resolvedUrl.replaceAll(RegExp(r'/$'), ''),
|
|
775
|
+
adminEmail: resolvedEmail,
|
|
776
|
+
adminPassword: resolvedPassword,
|
|
777
|
+
bundlesCollection: config.pocketbase.bundlesCollection,
|
|
778
|
+
channelsCollection: config.pocketbase.channelsCollection,
|
|
779
|
+
bundlesBucket: config.pocketbase.bundlesBucket,
|
|
780
|
+
clientFactory: clientFactory,
|
|
781
|
+
);
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
/// Resolve the PocketBase storage config (shares the database connection).
|
|
785
|
+
PocketBaseStorageConfig resolvePocketBaseStorageConfig(
|
|
786
|
+
FlutterPatcherConfig config, {
|
|
787
|
+
String? url,
|
|
788
|
+
String? adminEmail,
|
|
789
|
+
String? adminPassword,
|
|
790
|
+
String? bundlesBucket,
|
|
791
|
+
String? basePath,
|
|
792
|
+
PocketBaseClientFactory? clientFactory,
|
|
793
|
+
}) {
|
|
794
|
+
final db = resolvePocketBaseDatabaseConfig(
|
|
795
|
+
config,
|
|
796
|
+
url: url,
|
|
797
|
+
adminEmail: adminEmail,
|
|
798
|
+
adminPassword: adminPassword,
|
|
799
|
+
clientFactory: clientFactory,
|
|
800
|
+
);
|
|
801
|
+
return PocketBaseStorageConfig(
|
|
802
|
+
url: db.url,
|
|
803
|
+
adminEmail: db.adminEmail,
|
|
804
|
+
adminPassword: db.adminPassword,
|
|
805
|
+
bundlesCollection: db.bundlesCollection,
|
|
806
|
+
bundlesBucket: bundlesBucket ?? db.bundlesBucket,
|
|
807
|
+
basePath: basePath,
|
|
808
|
+
clientFactory: clientFactory,
|
|
809
|
+
);
|
|
810
|
+
}
|
|
@@ -65,7 +65,9 @@ Future<Bundle> deployBundle(Backend backend, DeployOptions opts) async {
|
|
|
65
65
|
// Otherwise, if the source directory contains a `patch.zip`, use that. As a
|
|
66
66
|
// fallback, zip the source directory (for pre-built bundle layouts).
|
|
67
67
|
final sourceFile = File(opts.source);
|
|
68
|
-
final bool sourceIsFile =
|
|
68
|
+
final bool sourceIsFile =
|
|
69
|
+
sourceFile.existsSync() &&
|
|
70
|
+
sourceFile.statSync().type == FileSystemEntityType.file;
|
|
69
71
|
final String zipPath;
|
|
70
72
|
final bool shouldDelete;
|
|
71
73
|
if (sourceIsFile && opts.source.endsWith('.zip')) {
|
|
@@ -113,7 +115,8 @@ Future<Bundle> deployBundle(Backend backend, DeployOptions opts) async {
|
|
|
113
115
|
targetAppVersion: opts.targetAppVersion,
|
|
114
116
|
fingerprintHash: opts.fingerprintHash,
|
|
115
117
|
metadata:
|
|
116
|
-
opts.metadata ??
|
|
118
|
+
opts.metadata ??
|
|
119
|
+
(signature != null ? BundleMetadata(signature: signature) : null),
|
|
117
120
|
rolloutCohortCount: defaultRolloutCohortCount,
|
|
118
121
|
);
|
|
119
122
|
|
|
@@ -140,7 +143,9 @@ Future<Paginated<List<Bundle>>> listBundles(
|
|
|
140
143
|
DatabaseBundleQueryOptions(
|
|
141
144
|
where: DatabaseBundleQueryWhere(
|
|
142
145
|
channel: opts.channel,
|
|
143
|
-
platform: opts.platform != null
|
|
146
|
+
platform: opts.platform != null
|
|
147
|
+
? Platform.fromValue(opts.platform!)
|
|
148
|
+
: null,
|
|
144
149
|
enabled: opts.enabled,
|
|
145
150
|
),
|
|
146
151
|
limit: opts.limit,
|
|
@@ -160,11 +165,7 @@ Future<void> deleteBundle(Backend backend, String id) async {
|
|
|
160
165
|
}
|
|
161
166
|
|
|
162
167
|
/// Promote a bundle to a channel (enable + assign channel).
|
|
163
|
-
Future<void> promoteBundle(
|
|
164
|
-
Backend backend,
|
|
165
|
-
String id,
|
|
166
|
-
String channel,
|
|
167
|
-
) async {
|
|
168
|
+
Future<void> promoteBundle(Backend backend, String id, String channel) async {
|
|
168
169
|
final existing = await backend.db.getBundleById(id);
|
|
169
170
|
if (existing == null) {
|
|
170
171
|
throw StateError('Bundle "$id" not found.');
|