@_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
|
@@ -14,7 +14,8 @@ const _defaultBundleFields = <String, Object?>{
|
|
|
14
14
|
'message': null,
|
|
15
15
|
'enabled': true,
|
|
16
16
|
'shouldForceUpdate': false,
|
|
17
|
-
'storageUri':
|
|
17
|
+
'storageUri':
|
|
18
|
+
'storage://my-app/00000000-0000-0000-0000-000000000000/bundle.zip',
|
|
18
19
|
'fingerprintHash': null,
|
|
19
20
|
};
|
|
20
21
|
|
|
@@ -127,8 +128,7 @@ void _seedUpdateManifests(_FakeBlobStore store, List<Bundle> bundles) {
|
|
|
127
128
|
}
|
|
128
129
|
|
|
129
130
|
for (final entry in bundlesByKey.entries) {
|
|
130
|
-
final sorted = entry.value
|
|
131
|
-
..sort((a, b) => b.id.compareTo(a.id));
|
|
131
|
+
final sorted = entry.value..sort((a, b) => b.id.compareTo(a.id));
|
|
132
132
|
store.data[entry.key] = jsonEncode(sorted.map((b) => b.toJson()).toList());
|
|
133
133
|
}
|
|
134
134
|
|
|
@@ -159,10 +159,18 @@ void main() {
|
|
|
159
159
|
|
|
160
160
|
group('update checks', () {
|
|
161
161
|
test('uses direct app-version manifests for update checks', () async {
|
|
162
|
-
final latest = createBundle(
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
162
|
+
final latest = createBundle(
|
|
163
|
+
'production',
|
|
164
|
+
'ios',
|
|
165
|
+
'*',
|
|
166
|
+
'00000000-0000-0000-0000-000000000002',
|
|
167
|
+
);
|
|
168
|
+
final previous = createBundle(
|
|
169
|
+
'production',
|
|
170
|
+
'ios',
|
|
171
|
+
'*',
|
|
172
|
+
'00000000-0000-0000-0000-000000000001',
|
|
173
|
+
);
|
|
166
174
|
|
|
167
175
|
_seedUpdateManifests(store, [previous, latest]);
|
|
168
176
|
|
|
@@ -217,13 +225,20 @@ void main() {
|
|
|
217
225
|
|
|
218
226
|
test('respects cohort eligibility', () async {
|
|
219
227
|
final gatedBundle = Bundle.fromJson({
|
|
220
|
-
...createBundle(
|
|
221
|
-
|
|
222
|
-
|
|
228
|
+
...createBundle(
|
|
229
|
+
'production',
|
|
230
|
+
'ios',
|
|
231
|
+
'*',
|
|
232
|
+
'00000000-0000-0000-0000-000000000021',
|
|
233
|
+
).toJson(),
|
|
223
234
|
'targetCohorts': ['beta'],
|
|
224
235
|
});
|
|
225
|
-
final fallback = createBundle(
|
|
226
|
-
|
|
236
|
+
final fallback = createBundle(
|
|
237
|
+
'production',
|
|
238
|
+
'ios',
|
|
239
|
+
'*',
|
|
240
|
+
'00000000-0000-0000-0000-000000000020',
|
|
241
|
+
);
|
|
227
242
|
final fallbackWithCohort = Bundle.fromJson({
|
|
228
243
|
...fallback.toJson(),
|
|
229
244
|
'targetCohorts': ['stable'],
|
|
@@ -260,8 +275,12 @@ void main() {
|
|
|
260
275
|
|
|
261
276
|
group('append and commit', () {
|
|
262
277
|
test('appends a new bundle and commits to blob store', () async {
|
|
263
|
-
final bundle = createBundle(
|
|
264
|
-
|
|
278
|
+
final bundle = createBundle(
|
|
279
|
+
'production',
|
|
280
|
+
'ios',
|
|
281
|
+
'1.0.0',
|
|
282
|
+
'00000000-0000-0000-0000-000000000001',
|
|
283
|
+
);
|
|
265
284
|
|
|
266
285
|
await plugin.appendBundle(bundle);
|
|
267
286
|
await plugin.commitBundle();
|
|
@@ -273,14 +292,19 @@ void main() {
|
|
|
273
292
|
expect(stored.length, equals(1));
|
|
274
293
|
|
|
275
294
|
final fetched = await plugin.getBundleById(
|
|
276
|
-
|
|
295
|
+
'00000000-0000-0000-0000-000000000001',
|
|
296
|
+
);
|
|
277
297
|
expect(fetched, isNotNull);
|
|
278
298
|
expect(fetched!.id, equals(bundle.id));
|
|
279
299
|
});
|
|
280
300
|
|
|
281
301
|
test('does not write to store until commitBundle', () async {
|
|
282
|
-
final bundle = createBundle(
|
|
283
|
-
|
|
302
|
+
final bundle = createBundle(
|
|
303
|
+
'production',
|
|
304
|
+
'ios',
|
|
305
|
+
'1.0.0',
|
|
306
|
+
'00000000-0000-0000-0000-000000000010',
|
|
307
|
+
);
|
|
284
308
|
|
|
285
309
|
expect(store.data, isEmpty);
|
|
286
310
|
|
|
@@ -288,35 +312,46 @@ void main() {
|
|
|
288
312
|
expect(store.data, isEmpty);
|
|
289
313
|
|
|
290
314
|
await plugin.commitBundle();
|
|
291
|
-
expect(
|
|
315
|
+
expect(
|
|
316
|
+
store.data.containsKey('production/ios/1.0.0/update.json'),
|
|
317
|
+
isTrue,
|
|
318
|
+
);
|
|
292
319
|
});
|
|
293
320
|
|
|
294
321
|
test('appends multiple bundles to correct keys', () async {
|
|
295
322
|
final b1 = createBundle('production', 'ios', '1.0.0', 'multi-1');
|
|
296
|
-
final b2 =
|
|
297
|
-
createBundle('production', 'android', '2.0.0', 'multi-2');
|
|
323
|
+
final b2 = createBundle('production', 'android', '2.0.0', 'multi-2');
|
|
298
324
|
|
|
299
325
|
await plugin.appendBundle(b1);
|
|
300
326
|
await plugin.appendBundle(b2);
|
|
301
327
|
await plugin.commitBundle();
|
|
302
328
|
|
|
303
|
-
expect(
|
|
304
|
-
|
|
305
|
-
|
|
329
|
+
expect(
|
|
330
|
+
store.data.containsKey('production/ios/1.0.0/update.json'),
|
|
331
|
+
isTrue,
|
|
332
|
+
);
|
|
333
|
+
expect(
|
|
334
|
+
store.data.containsKey('production/android/2.0.0/update.json'),
|
|
335
|
+
isTrue,
|
|
336
|
+
);
|
|
306
337
|
});
|
|
307
338
|
});
|
|
308
339
|
|
|
309
340
|
group('update and delete', () {
|
|
310
341
|
test('updates an existing bundle', () async {
|
|
311
|
-
final bundle = createBundle(
|
|
312
|
-
|
|
342
|
+
final bundle = createBundle(
|
|
343
|
+
'production',
|
|
344
|
+
'android',
|
|
345
|
+
'2.0.0',
|
|
346
|
+
'00000000-0000-0000-0000-000000000002',
|
|
347
|
+
);
|
|
313
348
|
final bundleKey = 'production/android/2.0.0/update.json';
|
|
314
349
|
store.data[bundleKey] = jsonEncode([bundle.toJson()]);
|
|
315
350
|
|
|
316
|
-
await plugin.getBundles(
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
351
|
+
await plugin.getBundles(const DatabaseBundleQueryOptions(limit: 20));
|
|
352
|
+
await plugin.updateBundle('00000000-0000-0000-0000-000000000002', {
|
|
353
|
+
'enabled': false,
|
|
354
|
+
});
|
|
320
355
|
await plugin.commitBundle();
|
|
321
356
|
|
|
322
357
|
final updated = jsonDecode(store.data[bundleKey]!) as List;
|
|
@@ -332,10 +367,8 @@ void main() {
|
|
|
332
367
|
});
|
|
333
368
|
|
|
334
369
|
test('deletes a bundle successfully', () async {
|
|
335
|
-
final b1 = createBundle(
|
|
336
|
-
|
|
337
|
-
final b2 = createBundle(
|
|
338
|
-
'production', 'android', '1.1.1', 'bundleY');
|
|
370
|
+
final b1 = createBundle('production', 'ios', '1.1.1', 'bundleX');
|
|
371
|
+
final b2 = createBundle('production', 'android', '1.1.1', 'bundleY');
|
|
339
372
|
|
|
340
373
|
await plugin.appendBundle(b1);
|
|
341
374
|
await plugin.appendBundle(b2);
|
|
@@ -351,14 +384,14 @@ void main() {
|
|
|
351
384
|
});
|
|
352
385
|
|
|
353
386
|
test('deletes entire update.json when no bundles remain', () async {
|
|
354
|
-
final b1 = createBundle(
|
|
355
|
-
'production', 'ios', '1.1.1', 'bundleX');
|
|
387
|
+
final b1 = createBundle('production', 'ios', '1.1.1', 'bundleX');
|
|
356
388
|
|
|
357
389
|
await plugin.appendBundle(b1);
|
|
358
390
|
await plugin.commitBundle();
|
|
359
391
|
|
|
360
|
-
final updateJsonKeys =
|
|
361
|
-
|
|
392
|
+
final updateJsonKeys = store.data.keys
|
|
393
|
+
.where((k) => k.contains('update.json'))
|
|
394
|
+
.toList();
|
|
362
395
|
expect(updateJsonKeys, isNotEmpty);
|
|
363
396
|
|
|
364
397
|
await plugin.deleteBundle(b1);
|
|
@@ -368,10 +401,20 @@ void main() {
|
|
|
368
401
|
});
|
|
369
402
|
|
|
370
403
|
test('keeps update.json when other bundles remain', () async {
|
|
371
|
-
final b1 = {
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
'
|
|
404
|
+
final b1 = {
|
|
405
|
+
..._defaultBundleFields,
|
|
406
|
+
'id': 'bundleA',
|
|
407
|
+
'channel': 'production',
|
|
408
|
+
'platform': 'ios',
|
|
409
|
+
'targetAppVersion': '1.1.1',
|
|
410
|
+
};
|
|
411
|
+
final b2 = {
|
|
412
|
+
..._defaultBundleFields,
|
|
413
|
+
'id': 'bundleB',
|
|
414
|
+
'channel': 'production',
|
|
415
|
+
'platform': 'ios',
|
|
416
|
+
'targetAppVersion': '1.1.1',
|
|
417
|
+
};
|
|
375
418
|
|
|
376
419
|
final bundle1 = Bundle.fromJson(b1);
|
|
377
420
|
final bundle2 = Bundle.fromJson(b2);
|
|
@@ -394,25 +437,51 @@ void main() {
|
|
|
394
437
|
final keyNew = 'production/ios/1.0.2/update.json';
|
|
395
438
|
|
|
396
439
|
final oldBundles = [
|
|
397
|
-
createBundle(
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
440
|
+
createBundle(
|
|
441
|
+
'production',
|
|
442
|
+
'ios',
|
|
443
|
+
'1.x.x',
|
|
444
|
+
'00000000-0000-0000-0000-000000000003',
|
|
445
|
+
),
|
|
446
|
+
createBundle(
|
|
447
|
+
'production',
|
|
448
|
+
'ios',
|
|
449
|
+
'1.x.x',
|
|
450
|
+
'00000000-0000-0000-0000-000000000002',
|
|
451
|
+
),
|
|
452
|
+
createBundle(
|
|
453
|
+
'production',
|
|
454
|
+
'ios',
|
|
455
|
+
'1.x.x',
|
|
456
|
+
'00000000-0000-0000-0000-000000000001',
|
|
457
|
+
),
|
|
403
458
|
];
|
|
404
459
|
|
|
405
460
|
final newBundles = [
|
|
406
|
-
createBundle(
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
461
|
+
createBundle(
|
|
462
|
+
'production',
|
|
463
|
+
'ios',
|
|
464
|
+
'1.0.2',
|
|
465
|
+
'00000000-0000-0000-0000-000000000005',
|
|
466
|
+
),
|
|
467
|
+
createBundle(
|
|
468
|
+
'production',
|
|
469
|
+
'ios',
|
|
470
|
+
'1.0.2',
|
|
471
|
+
'00000000-0000-0000-0000-000000000004',
|
|
472
|
+
),
|
|
410
473
|
];
|
|
411
474
|
|
|
412
|
-
store.data[keyOld] = jsonEncode(
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
475
|
+
store.data[keyOld] = jsonEncode(
|
|
476
|
+
oldBundles.map((b) => b.toJson()).toList(),
|
|
477
|
+
);
|
|
478
|
+
store.data[keyNew] = jsonEncode(
|
|
479
|
+
newBundles.map((b) => b.toJson()).toList(),
|
|
480
|
+
);
|
|
481
|
+
store.data['production/ios/target-app-versions.json'] = jsonEncode([
|
|
482
|
+
'1.x.x',
|
|
483
|
+
'1.0.2',
|
|
484
|
+
]);
|
|
416
485
|
|
|
417
486
|
await plugin.getBundles(const DatabaseBundleQueryOptions(limit: 20));
|
|
418
487
|
|
|
@@ -445,8 +514,9 @@ void main() {
|
|
|
445
514
|
|
|
446
515
|
group('getBundles', () {
|
|
447
516
|
test('returns empty for no data', () async {
|
|
448
|
-
final result =
|
|
449
|
-
|
|
517
|
+
final result = await plugin.getBundles(
|
|
518
|
+
const DatabaseBundleQueryOptions(limit: 20),
|
|
519
|
+
);
|
|
450
520
|
expect(result.data, isEmpty);
|
|
451
521
|
expect(result.pagination.total, equals(0));
|
|
452
522
|
});
|
|
@@ -456,13 +526,17 @@ void main() {
|
|
|
456
526
|
final bB = createBundle('production', 'ios', '1.0.0', 'B');
|
|
457
527
|
final bC = createBundle('production', 'ios', '2.0.0', 'C');
|
|
458
528
|
|
|
459
|
-
store.data['production/ios/1.0.0/update.json'] =
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
529
|
+
store.data['production/ios/1.0.0/update.json'] = jsonEncode([
|
|
530
|
+
bB.toJson(),
|
|
531
|
+
bA.toJson(),
|
|
532
|
+
]);
|
|
533
|
+
store.data['production/ios/2.0.0/update.json'] = jsonEncode([
|
|
534
|
+
bC.toJson(),
|
|
535
|
+
]);
|
|
463
536
|
|
|
464
|
-
final result =
|
|
465
|
-
|
|
537
|
+
final result = await plugin.getBundles(
|
|
538
|
+
const DatabaseBundleQueryOptions(limit: 20),
|
|
539
|
+
);
|
|
466
540
|
expect(result.data.length, equals(3));
|
|
467
541
|
expect(result.data[0].id, 'C');
|
|
468
542
|
expect(result.data[1].id, 'B');
|
|
@@ -471,21 +545,29 @@ void main() {
|
|
|
471
545
|
|
|
472
546
|
test('filters by channel and platform', () async {
|
|
473
547
|
final ios = createBundle('production', 'ios', '1.0.0', 'ios-1');
|
|
474
|
-
final android =
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
548
|
+
final android = createBundle(
|
|
549
|
+
'production',
|
|
550
|
+
'android',
|
|
551
|
+
'1.0.0',
|
|
552
|
+
'android-1',
|
|
553
|
+
);
|
|
554
|
+
|
|
555
|
+
store.data['production/ios/1.0.0/update.json'] = jsonEncode([
|
|
556
|
+
ios.toJson(),
|
|
557
|
+
]);
|
|
558
|
+
store.data['production/android/1.0.0/update.json'] = jsonEncode([
|
|
559
|
+
android.toJson(),
|
|
560
|
+
]);
|
|
561
|
+
|
|
562
|
+
final result = await plugin.getBundles(
|
|
563
|
+
DatabaseBundleQueryOptions(
|
|
564
|
+
limit: 20,
|
|
565
|
+
where: const DatabaseBundleQueryWhere(
|
|
566
|
+
channel: 'production',
|
|
567
|
+
platform: Platform.ios,
|
|
568
|
+
),
|
|
487
569
|
),
|
|
488
|
-
)
|
|
570
|
+
);
|
|
489
571
|
expect(result.data.length, equals(1));
|
|
490
572
|
expect(result.data[0].id, 'ios-1');
|
|
491
573
|
});
|
|
@@ -493,16 +575,21 @@ void main() {
|
|
|
493
575
|
|
|
494
576
|
group('CloudFront invalidation', () {
|
|
495
577
|
test('invalidates correct paths on new bundle', () async {
|
|
496
|
-
final bundle = createBundle(
|
|
497
|
-
|
|
578
|
+
final bundle = createBundle(
|
|
579
|
+
'production',
|
|
580
|
+
'ios',
|
|
581
|
+
'1.0.0',
|
|
582
|
+
'cloudfront-new-test',
|
|
583
|
+
);
|
|
498
584
|
|
|
499
585
|
await plugin.appendBundle(bundle);
|
|
500
586
|
await plugin.commitBundle();
|
|
501
587
|
|
|
502
588
|
expect(store.invalidationCalls, isNotEmpty);
|
|
503
589
|
expect(
|
|
504
|
-
store.invalidationCalls
|
|
505
|
-
|
|
590
|
+
store.invalidationCalls.any(
|
|
591
|
+
(p) => p.contains('app-version') && p.contains('1.0.0'),
|
|
592
|
+
),
|
|
506
593
|
isTrue,
|
|
507
594
|
);
|
|
508
595
|
expect(
|
|
@@ -512,16 +599,21 @@ void main() {
|
|
|
512
599
|
});
|
|
513
600
|
|
|
514
601
|
test('invalidates semver pattern path', () async {
|
|
515
|
-
final bundle = createBundle(
|
|
516
|
-
|
|
602
|
+
final bundle = createBundle(
|
|
603
|
+
'production',
|
|
604
|
+
'ios',
|
|
605
|
+
'3.0.x',
|
|
606
|
+
'cloudfront-semver',
|
|
607
|
+
);
|
|
517
608
|
|
|
518
609
|
store.invalidationCalls.clear();
|
|
519
610
|
await plugin.appendBundle(bundle);
|
|
520
611
|
await plugin.commitBundle();
|
|
521
612
|
|
|
522
613
|
expect(
|
|
523
|
-
store.invalidationCalls
|
|
524
|
-
|
|
614
|
+
store.invalidationCalls.any(
|
|
615
|
+
(p) => p == '/api/check-update/app-version/ios/*',
|
|
616
|
+
),
|
|
525
617
|
isTrue,
|
|
526
618
|
);
|
|
527
619
|
});
|
|
@@ -535,26 +627,37 @@ void main() {
|
|
|
535
627
|
|
|
536
628
|
group('targetAppVersion with spaces', () {
|
|
537
629
|
test('normalizes space-containing targetAppVersion', () async {
|
|
538
|
-
final bundle = createBundle(
|
|
539
|
-
|
|
630
|
+
final bundle = createBundle(
|
|
631
|
+
'production',
|
|
632
|
+
'ios',
|
|
633
|
+
'>= 10.7.0',
|
|
634
|
+
'space-normalization-test',
|
|
635
|
+
);
|
|
540
636
|
|
|
541
637
|
await plugin.appendBundle(bundle);
|
|
542
638
|
await plugin.commitBundle();
|
|
543
639
|
|
|
544
|
-
expect(
|
|
545
|
-
|
|
640
|
+
expect(
|
|
641
|
+
store.data.containsKey('production/ios/>=10.7.0/update.json'),
|
|
642
|
+
isTrue,
|
|
643
|
+
);
|
|
546
644
|
});
|
|
547
645
|
|
|
548
646
|
test('normalizes multiple spaces', () async {
|
|
549
|
-
final bundle = createBundle(
|
|
550
|
-
|
|
647
|
+
final bundle = createBundle(
|
|
648
|
+
'production',
|
|
649
|
+
'android',
|
|
650
|
+
'> 1.0.0 < 2.0.0',
|
|
651
|
+
'multi-space-test',
|
|
652
|
+
);
|
|
551
653
|
|
|
552
654
|
await plugin.appendBundle(bundle);
|
|
553
655
|
await plugin.commitBundle();
|
|
554
656
|
|
|
555
657
|
expect(
|
|
556
|
-
|
|
557
|
-
|
|
658
|
+
store.data.containsKey('production/android/>1.0.0 <2.0.0/update.json'),
|
|
659
|
+
isTrue,
|
|
660
|
+
);
|
|
558
661
|
});
|
|
559
662
|
|
|
560
663
|
test('handles various semver range formats', () async {
|
|
@@ -585,30 +688,38 @@ void main() {
|
|
|
585
688
|
});
|
|
586
689
|
|
|
587
690
|
test('normalizes target-app-versions.json', () async {
|
|
588
|
-
final bundle = createBundle(
|
|
589
|
-
|
|
691
|
+
final bundle = createBundle(
|
|
692
|
+
'production',
|
|
693
|
+
'ios',
|
|
694
|
+
'>= 10.7.0',
|
|
695
|
+
'target-versions-test',
|
|
696
|
+
);
|
|
590
697
|
|
|
591
698
|
await plugin.appendBundle(bundle);
|
|
592
699
|
await plugin.commitBundle();
|
|
593
700
|
|
|
594
701
|
final versions = jsonDecode(
|
|
595
|
-
|
|
702
|
+
store.data['production/ios/target-app-versions.json']!,
|
|
703
|
+
) as List;
|
|
596
704
|
expect(versions, contains('>=10.7.0'));
|
|
597
705
|
});
|
|
598
706
|
});
|
|
599
707
|
|
|
600
708
|
group('semver normalization', () {
|
|
601
709
|
test('invalidates all paths for 1.0.0', () async {
|
|
602
|
-
final bundle = createBundle(
|
|
603
|
-
|
|
710
|
+
final bundle = createBundle(
|
|
711
|
+
'production',
|
|
712
|
+
'ios',
|
|
713
|
+
'1.0.0',
|
|
714
|
+
'semver-normalization-test',
|
|
715
|
+
);
|
|
604
716
|
|
|
605
717
|
store.invalidationCalls.clear();
|
|
606
718
|
await plugin.appendBundle(bundle);
|
|
607
719
|
await plugin.commitBundle();
|
|
608
720
|
|
|
609
721
|
expect(
|
|
610
|
-
store.invalidationCalls
|
|
611
|
-
.any((p) => p.contains('app-version/ios/1.0.0')),
|
|
722
|
+
store.invalidationCalls.any((p) => p.contains('app-version/ios/1.0.0')),
|
|
612
723
|
isTrue,
|
|
613
724
|
);
|
|
614
725
|
expect(
|
|
@@ -622,32 +733,44 @@ void main() {
|
|
|
622
733
|
});
|
|
623
734
|
|
|
624
735
|
test('only normalizes 2.x when patch=0', () async {
|
|
625
|
-
final bundle = createBundle(
|
|
626
|
-
|
|
736
|
+
final bundle = createBundle(
|
|
737
|
+
'production',
|
|
738
|
+
'android',
|
|
739
|
+
'2.1.0',
|
|
740
|
+
'semver-norm-test-2',
|
|
741
|
+
);
|
|
627
742
|
|
|
628
743
|
store.invalidationCalls.clear();
|
|
629
744
|
await plugin.appendBundle(bundle);
|
|
630
745
|
await plugin.commitBundle();
|
|
631
746
|
|
|
632
747
|
expect(
|
|
633
|
-
store.invalidationCalls
|
|
634
|
-
|
|
748
|
+
store.invalidationCalls.any(
|
|
749
|
+
(p) => p.contains('app-version/android/2.1.0'),
|
|
750
|
+
),
|
|
635
751
|
isTrue,
|
|
636
752
|
);
|
|
637
753
|
expect(
|
|
638
|
-
store.invalidationCalls.any(
|
|
754
|
+
store.invalidationCalls.any(
|
|
755
|
+
(p) => p.contains('app-version/android/2.1'),
|
|
756
|
+
),
|
|
639
757
|
isTrue,
|
|
640
758
|
);
|
|
641
759
|
expect(
|
|
642
|
-
store.invalidationCalls
|
|
643
|
-
|
|
760
|
+
store.invalidationCalls.any(
|
|
761
|
+
(p) => RegExp(r'app-version/android/2/').hasMatch(p),
|
|
762
|
+
),
|
|
644
763
|
isFalse,
|
|
645
764
|
);
|
|
646
765
|
});
|
|
647
766
|
|
|
648
767
|
test('no extra normalization for 1.2.3', () async {
|
|
649
|
-
final bundle = createBundle(
|
|
650
|
-
|
|
768
|
+
final bundle = createBundle(
|
|
769
|
+
'production',
|
|
770
|
+
'ios',
|
|
771
|
+
'1.2.3',
|
|
772
|
+
'no-normalization-test',
|
|
773
|
+
);
|
|
651
774
|
|
|
652
775
|
store.invalidationCalls.clear();
|
|
653
776
|
await plugin.appendBundle(bundle);
|
|
@@ -655,17 +778,20 @@ void main() {
|
|
|
655
778
|
|
|
656
779
|
expect(
|
|
657
780
|
store.invalidationCalls.any(
|
|
658
|
-
|
|
781
|
+
(p) => p == '/api/check-update/app-version/ios/1.2.3/production/*',
|
|
782
|
+
),
|
|
659
783
|
isTrue,
|
|
660
784
|
);
|
|
661
785
|
expect(
|
|
662
786
|
store.invalidationCalls.any(
|
|
663
|
-
|
|
787
|
+
(p) => p == '/api/check-update/app-version/ios/1.2/production/*',
|
|
788
|
+
),
|
|
664
789
|
isFalse,
|
|
665
790
|
);
|
|
666
791
|
expect(
|
|
667
792
|
store.invalidationCalls.any(
|
|
668
|
-
|
|
793
|
+
(p) => p == '/api/check-update/app-version/ios/1/production/*',
|
|
794
|
+
),
|
|
669
795
|
isFalse,
|
|
670
796
|
);
|
|
671
797
|
});
|
|
@@ -673,8 +799,12 @@ void main() {
|
|
|
673
799
|
|
|
674
800
|
group('issue #745 promotion scenario', () {
|
|
675
801
|
test('updates target-app-versions when promoting channel', () async {
|
|
676
|
-
final bundle = createBundle(
|
|
677
|
-
|
|
802
|
+
final bundle = createBundle(
|
|
803
|
+
'test',
|
|
804
|
+
'android',
|
|
805
|
+
'8.1.3',
|
|
806
|
+
'issue-745-promote-bundle',
|
|
807
|
+
);
|
|
678
808
|
|
|
679
809
|
await plugin.appendBundle(bundle);
|
|
680
810
|
await plugin.commitBundle();
|
|
@@ -687,24 +817,26 @@ void main() {
|
|
|
687
817
|
await plugin.commitBundle();
|
|
688
818
|
|
|
689
819
|
expect(
|
|
690
|
-
store.invalidationCalls
|
|
691
|
-
|
|
820
|
+
store.invalidationCalls.any(
|
|
821
|
+
(p) => p.contains('app-version/android/8.1.3/test'),
|
|
822
|
+
),
|
|
692
823
|
isTrue,
|
|
693
824
|
);
|
|
694
825
|
expect(
|
|
695
|
-
store.invalidationCalls
|
|
696
|
-
|
|
826
|
+
store.invalidationCalls.any(
|
|
827
|
+
(p) => p.contains('app-version/android/8.1.3/prod'),
|
|
828
|
+
),
|
|
697
829
|
isTrue,
|
|
698
830
|
);
|
|
699
831
|
|
|
700
832
|
final prodVersions = jsonDecode(
|
|
701
|
-
|
|
702
|
-
|
|
833
|
+
store.data['prod/android/target-app-versions.json'] ?? '[]',
|
|
834
|
+
) as List;
|
|
703
835
|
expect(prodVersions, contains('8.1.3'));
|
|
704
836
|
|
|
705
837
|
final testVersions = jsonDecode(
|
|
706
|
-
|
|
707
|
-
|
|
838
|
+
store.data['test/android/target-app-versions.json'] ?? '[]',
|
|
839
|
+
) as List;
|
|
708
840
|
expect(testVersions, isNot(contains('8.1.3')));
|
|
709
841
|
});
|
|
710
842
|
});
|