@_nazmiforreal/flutter-ota 0.1.5 → 0.1.7
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 +13 -13
- package/bin/{flutter-patcher-linux-x64 → flutter-ota-linux-x64} +0 -0
- package/bin/{flutter-patcher.js → flutter-ota.js} +4 -4
- package/dart-src/packages/cli-tools/bin/{flutter_patcher.dart → flutter_ota_kit.dart} +2 -2
- package/dart-src/packages/cli-tools/lib/{flutter_patcher_cli.dart → flutter_ota_kit_cli.dart} +5 -3
- package/dart-src/packages/cli-tools/lib/src/backend.dart +6 -25
- package/dart-src/packages/cli-tools/lib/src/cli_base.dart +10 -4
- package/dart-src/packages/cli-tools/lib/src/commands/build.dart +5 -3
- package/dart-src/packages/cli-tools/lib/src/commands/bundle.dart +279 -10
- package/dart-src/packages/cli-tools/lib/src/commands/channel.dart +7 -7
- package/dart-src/packages/cli-tools/lib/src/commands/config_command.dart +5 -5
- package/dart-src/packages/cli-tools/lib/src/commands/console.dart +4 -4
- package/dart-src/packages/cli-tools/lib/src/commands/deploy.dart +4 -4
- package/dart-src/packages/cli-tools/lib/src/commands/doctor.dart +3 -3
- package/dart-src/packages/cli-tools/lib/src/commands/fingerprint.dart +1 -1
- package/dart-src/packages/cli-tools/lib/src/commands/init.dart +294 -45
- package/dart-src/packages/cli-tools/lib/src/commands/keys.dart +1 -1
- package/dart-src/packages/cli-tools/lib/src/commands/migrate.dart +218 -69
- package/dart-src/packages/cli-tools/lib/src/commands/rollback.dart +5 -5
- package/dart-src/packages/cli-tools/lib/src/commands/storage.dart +117 -0
- package/dart-src/packages/cli-tools/lib/src/config.dart +29 -78
- package/dart-src/packages/cli-tools/lib/src/operations.dart +4 -4
- package/dart-src/packages/cli-tools/lib/src/pack.dart +12 -6
- package/dart-src/packages/cli-tools/lib/src/runner.dart +25 -6
- package/dart-src/packages/cli-tools/lib/src/ui/ui.dart +5 -3
- package/dart-src/packages/cli-tools/lib/src/verbose.dart +3 -0
- package/dart-src/packages/cli-tools/migrations/aws/README.md +7 -0
- package/dart-src/packages/cli-tools/migrations/postgres/bundles.sql +45 -0
- package/dart-src/packages/cli-tools/migrations/postgres/get_target_app_version_list.sql +21 -0
- package/dart-src/packages/cli-tools/migrations/postgres/get_update_info_by_app_version.sql +126 -0
- package/dart-src/packages/cli-tools/migrations/postgres/get_update_info_by_fingerprint_hash.sql +125 -0
- package/dart-src/packages/cli-tools/migrations/postgres/hash_user_id.sql +30 -0
- package/dart-src/packages/cli-tools/migrations/postgres/is_device_eligible.sql +237 -0
- package/dart-src/packages/cli-tools/migrations/supabase/20260520014100_hot-updater_rls.sql +11 -0
- package/dart-src/packages/cli-tools/pubspec.yaml +9 -11
- package/dart-src/packages/cli-tools/test/backends_test.dart +4 -4
- package/dart-src/packages/cli-tools/test/build_pack_test.dart +1 -1
- package/dart-src/packages/cli-tools/test/cli_test.dart +3 -3
- package/dart-src/packages/cli-tools/test/mocks/mock_aws_s3_client.dart +2 -2
- package/dart-src/packages/cli-tools/test/mocks/mock_d1_client.dart +2 -2
- package/dart-src/packages/cli-tools/test/mocks/mock_postgres_client.dart +7 -7
- package/dart-src/packages/core/lib/{flutter_patcher_core.dart → flutter_ota_kit_core.dart} +1 -1
- package/dart-src/packages/core/pubspec.yaml +2 -2
- package/dart-src/packages/core/test/rollout_test.dart +1 -1
- package/dart-src/packages/core/test/semver_test.dart +1 -1
- package/dart-src/packages/core/test/types_test.dart +2 -2
- package/dart-src/packages/core/test/uuid_test.dart +1 -1
- package/dart-src/packages/core/tool/dbg.dart +1 -1
- package/dart-src/plugins/aws/lib/{flutter_patcher_aws.dart → flutter_ota_kit_aws.dart} +0 -2
- package/dart-src/plugins/aws/lib/src/aws_cloudfront_client.dart +1 -1
- package/dart-src/plugins/aws/lib/src/aws_database.dart +1 -1
- package/dart-src/plugins/aws/lib/src/aws_s3_client.dart +1 -1
- package/dart-src/plugins/aws/lib/src/aws_storage.dart +1 -1
- package/dart-src/plugins/aws/lib/src/aws_storage_profile.dart +25 -3
- package/dart-src/plugins/aws/lib/src/with_cloudfront_signed_url.dart +1 -1
- package/dart-src/plugins/aws/pubspec.yaml +4 -4
- package/dart-src/plugins/aws/test/aws_database_test.dart +3 -3
- package/dart-src/plugins/aws/test/aws_storage_test.dart +2 -2
- package/dart-src/plugins/aws/test/mock_aws_s3_client.dart +2 -2
- package/dart-src/plugins/cloudflare/lib/src/cloudflare_worker_database.dart +1 -1
- package/dart-src/plugins/cloudflare/lib/src/d1_build_where.dart +1 -1
- package/dart-src/plugins/cloudflare/lib/src/d1_bundle_mapper.dart +1 -1
- package/dart-src/plugins/cloudflare/lib/src/d1_database.dart +1 -1
- package/dart-src/plugins/cloudflare/lib/src/d1_database_plugin.dart +2 -2
- package/dart-src/plugins/cloudflare/lib/src/r2_s3_client.dart +1 -1
- package/dart-src/plugins/cloudflare/lib/src/r2_storage.dart +1 -1
- package/dart-src/plugins/cloudflare/lib/src/r2_storage_profile.dart +1 -1
- package/dart-src/plugins/cloudflare/pubspec.yaml +4 -4
- package/dart-src/plugins/cloudflare/test/cloudflare_worker_database_test.dart +2 -2
- package/dart-src/plugins/cloudflare/test/d1_bundle_mapper_test.dart +2 -2
- package/dart-src/plugins/cloudflare/test/d1_database_test.dart +2 -2
- package/dart-src/plugins/cloudflare/test/mock_d1_client.dart +2 -2
- package/dart-src/plugins/cloudflare/test/mock_r2_client.dart +2 -2
- package/dart-src/plugins/cloudflare/test/r2_storage_test.dart +2 -2
- package/dart-src/plugins/plugin-core/lib/{flutter_patcher_plugin_core.dart → flutter_ota_kit_plugin_core.dart} +1 -1
- package/dart-src/plugins/plugin-core/lib/src/create_blob_database_plugin.dart +1 -1
- package/dart-src/plugins/plugin-core/lib/src/filter_compatible_app_versions.dart +1 -1
- package/dart-src/plugins/plugin-core/lib/src/get_update_info.dart +1 -1
- package/dart-src/plugins/plugin-core/lib/src/request_update_bundle_state.dart +1 -1
- package/dart-src/plugins/plugin-core/lib/src/resolve_update_info_from_bundles.dart +1 -1
- package/dart-src/plugins/plugin-core/lib/src/types.dart +2 -2
- package/dart-src/plugins/plugin-core/pubspec.yaml +3 -3
- package/dart-src/plugins/plugin-core/test/asset_storage_layout_test.dart +3 -3
- package/dart-src/plugins/plugin-core/test/bundle_unit_of_work_store_test.dart +2 -2
- package/dart-src/plugins/plugin-core/test/bundle_unit_of_work_test.dart +2 -2
- package/dart-src/plugins/plugin-core/test/create_blob_database_plugin_test.dart +2 -2
- package/dart-src/plugins/plugin-core/test/create_database_plugin_test.dart +5 -5
- package/dart-src/plugins/plugin-core/test/create_storage_plugin_test.dart +2 -2
- package/dart-src/plugins/plugin-core/test/generate_min_bundle_id_test.dart +2 -2
- package/dart-src/plugins/plugin-core/test/get_update_info_test.dart +2 -2
- package/dart-src/plugins/plugin-core/test/helpers_test.dart +2 -2
- package/dart-src/plugins/plugin-core/test/query_bundles_test.dart +2 -2
- package/dart-src/plugins/plugin-core/test/request_update_bundle_state_test.dart +3 -3
- package/dart-src/plugins/plugin-core/test/uuidv7_test.dart +1 -1
- package/dart-src/plugins/postgres/lib/{flutter_patcher_postgres.dart → flutter_ota_kit_postgres.dart} +1 -1
- package/dart-src/plugins/postgres/lib/src/postgres_bundle_mapper.dart +1 -1
- package/dart-src/plugins/postgres/lib/src/postgres_database.dart +2 -2
- package/dart-src/plugins/postgres/lib/src/postgres_get_update_info.dart +2 -2
- package/dart-src/plugins/postgres/lib/src/postgres_storage.dart +9 -9
- package/dart-src/plugins/postgres/lib/src/postgres_types.dart +1 -1
- package/dart-src/plugins/postgres/pubspec.yaml +4 -4
- package/dart-src/plugins/postgres/test/mock_postgres_client.dart +2 -2
- package/dart-src/plugins/postgres/test/postgres_bundle_mapper_test.dart +2 -2
- package/dart-src/plugins/postgres/test/postgres_database_test.dart +2 -2
- package/dart-src/plugins/supabase/lib/edge.dart +1 -1
- package/dart-src/plugins/supabase/lib/{flutter_patcher_supabase.dart → flutter_ota_kit_supabase.dart} +1 -1
- package/dart-src/plugins/supabase/lib/src/supabase_bundle_mapper.dart +1 -1
- package/dart-src/plugins/supabase/lib/src/supabase_client_http.dart +60 -20
- package/dart-src/plugins/supabase/lib/src/supabase_database.dart +2 -2
- package/dart-src/plugins/supabase/lib/src/supabase_edge_function_database.dart +1 -1
- package/dart-src/plugins/supabase/lib/src/supabase_edge_function_storage.dart +1 -1
- package/dart-src/plugins/supabase/lib/src/supabase_storage.dart +2 -5
- package/dart-src/plugins/supabase/pubspec.yaml +4 -4
- package/dart-src/plugins/supabase/test/mock_supabase_client.dart +5 -5
- package/dart-src/plugins/supabase/test/supabase_bundle_mapper_test.dart +3 -3
- package/dart-src/plugins/supabase/test/supabase_database_test.dart +3 -3
- package/dart-src/plugins/supabase/test/supabase_storage_test.dart +2 -2
- package/migrations/aws/README.md +7 -0
- package/migrations/cloudflare/0001_hot-updater_init.sql +16 -0
- package/migrations/cloudflare/0002_hot-updater_0.13.0.sql +8 -0
- package/migrations/cloudflare/0003_hot-updater_0.18.0.sql +38 -0
- package/migrations/cloudflare/0004_hot-updater_0.29.0.sql +11 -0
- package/migrations/cloudflare/0005_hot-updater_0.31.0.sql +24 -0
- package/migrations/cloudflare/bundles.sql +42 -0
- package/migrations/postgres/bundles.sql +45 -0
- package/migrations/postgres/get_target_app_version_list.sql +21 -0
- package/migrations/postgres/get_update_info_by_app_version.sql +126 -0
- package/migrations/postgres/get_update_info_by_fingerprint_hash.sql +125 -0
- package/migrations/postgres/hash_user_id.sql +30 -0
- package/migrations/postgres/is_device_eligible.sql +237 -0
- package/package.json +4 -4
- package/scripts/postinstall.js +15 -15
- package/scripts/vendor.sh +1 -1
- package/dart-src/packages/cli-tools/.dart_tool/package_config.json +0 -496
- package/dart-src/packages/cli-tools/.dart_tool/package_graph.json +0 -743
- package/dart-src/packages/cli-tools/pubspec.lock +0 -638
- package/dart-src/packages/cli-tools/test/standalone_backend_test.dart +0 -315
- package/dart-src/plugins/aws/lib/src/aws_lambda_edge_storage.dart +0 -72
- package/dart-src/plugins/aws/test/aws_lambda_edge_storage_test.dart +0 -190
- package/dart-src/plugins/standalone/.gitkeep +0 -0
- package/dart-src/plugins/standalone/lib/flutter_patcher_standalone.dart +0 -12
- package/dart-src/plugins/standalone/lib/src/standalone_config.dart +0 -107
- package/dart-src/plugins/standalone/lib/src/standalone_database.dart +0 -233
- package/dart-src/plugins/standalone/lib/src/standalone_storage.dart +0 -175
- package/dart-src/plugins/standalone/pubspec.yaml +0 -18
- package/dart-src/plugins/standalone/test/standalone_test.dart +0 -264
- /package/dart-src/plugins/cloudflare/lib/{flutter_patcher_cloudflare.dart → flutter_ota_kit_cloudflare.dart} +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
name:
|
|
2
|
-
description: Postgres plugin for
|
|
1
|
+
name: flutter_ota_kit_postgres
|
|
2
|
+
description: Postgres plugin for flutter_ota_kit — database backend.
|
|
3
3
|
version: 0.1.0
|
|
4
4
|
publish_to: none
|
|
5
5
|
|
|
@@ -7,9 +7,9 @@ environment:
|
|
|
7
7
|
sdk: ">=3.3.0 <4.0.0"
|
|
8
8
|
|
|
9
9
|
dependencies:
|
|
10
|
-
|
|
10
|
+
flutter_ota_kit_core:
|
|
11
11
|
path: ../../packages/core
|
|
12
|
-
|
|
12
|
+
flutter_ota_kit_plugin_core:
|
|
13
13
|
path: ../../plugins/plugin-core
|
|
14
14
|
postgres: ^3.4.0
|
|
15
15
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import 'package:
|
|
1
|
+
import 'package:flutter_ota_kit_plugin_core/flutter_ota_kit_plugin_core.dart';
|
|
2
2
|
|
|
3
|
-
import 'package:
|
|
3
|
+
import 'package:flutter_ota_kit_postgres/flutter_ota_kit_postgres.dart';
|
|
4
4
|
|
|
5
5
|
/// In-memory store backing [MockPostgresClient]. Mirrors the `bundles` and
|
|
6
6
|
/// `bundle_patches` tables (snake_case row maps).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import 'package:
|
|
1
|
+
import 'package:flutter_ota_kit_core/flutter_ota_kit_core.dart'
|
|
2
2
|
show Bundle, BundleMetadata, BundlePatchArtifact, Platform;
|
|
3
|
-
import 'package:
|
|
3
|
+
import 'package:flutter_ota_kit_postgres/flutter_ota_kit_postgres.dart';
|
|
4
4
|
import 'package:test/test.dart';
|
|
5
5
|
|
|
6
6
|
void main() {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import 'package:
|
|
1
|
+
import 'package:flutter_ota_kit_core/flutter_ota_kit_core.dart'
|
|
2
2
|
show
|
|
3
3
|
AppVersionGetBundlesArgs,
|
|
4
4
|
Bundle,
|
|
@@ -7,7 +7,7 @@ import 'package:flutter_patcher_core/flutter_patcher_core.dart'
|
|
|
7
7
|
UpdateInfo,
|
|
8
8
|
UpdateStatus,
|
|
9
9
|
nilUuid;
|
|
10
|
-
import 'package:
|
|
10
|
+
import 'package:flutter_ota_kit_plugin_core/flutter_ota_kit_plugin_core.dart'
|
|
11
11
|
show
|
|
12
12
|
DatabaseBundleQueryOptions,
|
|
13
13
|
DatabaseBundleQueryWhere,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/// Edge-function entrypoint for
|
|
1
|
+
/// Edge-function entrypoint for flutter_ota_kit_supabase.
|
|
2
2
|
///
|
|
3
3
|
/// Mirrors hot-updater's `plugins/supabase/src/edge.ts`: exposes only the
|
|
4
4
|
/// edge-runnable variants (runtime-only database + storage plugins).
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
///
|
|
1
|
+
/// flutter_ota_kit_supabase — Supabase backend for flutter_ota_kit.
|
|
2
2
|
///
|
|
3
3
|
/// Faithful Dart translation of hot-updater's `plugins/supabase`:
|
|
4
4
|
/// database + storage plugins (direct + edge-function variants) over the
|
|
@@ -245,17 +245,23 @@ class _StorageBucket implements SupabaseStorageBucketLike {
|
|
|
245
245
|
String path,
|
|
246
246
|
int expiresIn,
|
|
247
247
|
) async {
|
|
248
|
-
final uri = Uri.parse(
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
248
|
+
final uri = Uri.parse('$_baseUrl/storage/v1/object/sign/$_bucket/$path');
|
|
249
|
+
final res = await http.post(
|
|
250
|
+
uri,
|
|
251
|
+
headers: {..._headers, 'Content-Type': 'application/json'},
|
|
252
|
+
body: jsonEncode({'expiresIn': expiresIn}),
|
|
253
|
+
);
|
|
252
254
|
if (res.statusCode >= 400) {
|
|
253
255
|
return _MockSignedUrlResult(null, jsonDecode(res.body));
|
|
254
256
|
}
|
|
255
257
|
final body = jsonDecode(res.body) as Map<String, dynamic>;
|
|
258
|
+
final signed = body['signedURL'] as String?;
|
|
259
|
+
// Supabase returns a relative path ("/object/sign/...?token=..."); make it
|
|
260
|
+
// absolute against the project base URL.
|
|
256
261
|
return _MockSignedUrlResult(
|
|
257
|
-
|
|
258
|
-
|
|
262
|
+
signed == null ? null : '$_baseUrl/storage/v1$signed',
|
|
263
|
+
null,
|
|
264
|
+
);
|
|
259
265
|
}
|
|
260
266
|
|
|
261
267
|
@override
|
|
@@ -279,7 +285,11 @@ class _StorageBucket implements SupabaseStorageBucketLike {
|
|
|
279
285
|
return _MockSignedUrlListResult(
|
|
280
286
|
body
|
|
281
287
|
.map((e) => _MockSignedUrlResult(
|
|
282
|
-
|
|
288
|
+
// Supabase returns a relative path; make it absolute against
|
|
289
|
+
// the project base URL, matching [createSignedUrl].
|
|
290
|
+
e['signedURL'] == null
|
|
291
|
+
? null
|
|
292
|
+
: '$_baseUrl/storage/v1${e['signedURL'] as String}',
|
|
283
293
|
e['error'] as String?,
|
|
284
294
|
))
|
|
285
295
|
.toList(),
|
|
@@ -287,6 +297,22 @@ class _StorageBucket implements SupabaseStorageBucketLike {
|
|
|
287
297
|
);
|
|
288
298
|
}
|
|
289
299
|
|
|
300
|
+
Future<void> _ensureBucket() async {
|
|
301
|
+
final res = await http.post(
|
|
302
|
+
Uri.parse('$_baseUrl/storage/v1/bucket'),
|
|
303
|
+
headers: {..._headers, 'Content-Type': 'application/json'},
|
|
304
|
+
body: jsonEncode({'name': _bucket, 'public': true}),
|
|
305
|
+
);
|
|
306
|
+
// 400/409 just mean it already exists — that's fine.
|
|
307
|
+
if (res.statusCode >= 400) {
|
|
308
|
+
final body = jsonDecode(res.body) as Map<String, dynamic>;
|
|
309
|
+
final msg = (body['message'] ?? body['error'] ?? '').toString();
|
|
310
|
+
if (!msg.contains('already exists') && res.statusCode != 409) {
|
|
311
|
+
throw StateError('Failed to create bucket "$_bucket": $msg');
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
290
316
|
@override
|
|
291
317
|
Future<SupabaseUploadResult> upload(
|
|
292
318
|
String path,
|
|
@@ -294,20 +320,34 @@ class _StorageBucket implements SupabaseStorageBucketLike {
|
|
|
294
320
|
String? contentType,
|
|
295
321
|
String? cacheControl,
|
|
296
322
|
}) async {
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
323
|
+
Future<_MockUploadResult> doUpload() async {
|
|
324
|
+
final uri = Uri.parse('$_baseUrl/storage/v1/object/$_bucket/$path');
|
|
325
|
+
final res = await http.post(
|
|
326
|
+
uri,
|
|
327
|
+
headers: {
|
|
328
|
+
..._headers,
|
|
329
|
+
'Content-Type': contentType ?? 'application/octet-stream',
|
|
330
|
+
if (cacheControl != null) 'Cache-Control': cacheControl,
|
|
331
|
+
},
|
|
332
|
+
body: fileBytes,
|
|
333
|
+
);
|
|
334
|
+
if (res.statusCode >= 400) {
|
|
335
|
+
return _MockUploadResult(null, jsonDecode(res.body));
|
|
336
|
+
}
|
|
337
|
+
return _MockUploadResult(jsonDecode(res.body), null);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
final first = await doUpload();
|
|
341
|
+
if (first.error != null) {
|
|
342
|
+
final msg =
|
|
343
|
+
(first.error is Map ? (first.error as Map)['message'] : first.error)
|
|
344
|
+
.toString();
|
|
345
|
+
if (msg.contains('Bucket not found')) {
|
|
346
|
+
await _ensureBucket();
|
|
347
|
+
return doUpload();
|
|
348
|
+
}
|
|
309
349
|
}
|
|
310
|
-
return
|
|
350
|
+
return first;
|
|
311
351
|
}
|
|
312
352
|
|
|
313
353
|
@override
|
|
@@ -3,8 +3,8 @@ library;
|
|
|
3
3
|
|
|
4
4
|
import 'dart:convert';
|
|
5
5
|
|
|
6
|
-
import 'package:
|
|
7
|
-
import 'package:
|
|
6
|
+
import 'package:flutter_ota_kit_core/flutter_ota_kit_core.dart';
|
|
7
|
+
import 'package:flutter_ota_kit_plugin_core/flutter_ota_kit_plugin_core.dart';
|
|
8
8
|
|
|
9
9
|
import 'supabase_bundle_mapper.dart';
|
|
10
10
|
import 'supabase_client_adapter.dart';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/// Faithful port of hot-updater `plugins/supabase/src/supabaseEdgeFunctionDatabase.ts`.
|
|
2
2
|
library;
|
|
3
3
|
|
|
4
|
-
import 'package:
|
|
4
|
+
import 'package:flutter_ota_kit_plugin_core/flutter_ota_kit_plugin_core.dart';
|
|
5
5
|
|
|
6
6
|
import 'supabase_database.dart';
|
|
7
7
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/// Faithful port of hot-updater `plugins/supabase/src/supabaseEdgeFunctionStorage.ts`.
|
|
2
2
|
library;
|
|
3
3
|
|
|
4
|
-
import 'package:
|
|
4
|
+
import 'package:flutter_ota_kit_plugin_core/flutter_ota_kit_plugin_core.dart';
|
|
5
5
|
|
|
6
6
|
import 'supabase_client_adapter.dart';
|
|
7
7
|
import 'supabase_client_http.dart';
|
|
@@ -3,7 +3,7 @@ library;
|
|
|
3
3
|
|
|
4
4
|
import 'dart:io' as io;
|
|
5
5
|
|
|
6
|
-
import 'package:
|
|
6
|
+
import 'package:flutter_ota_kit_plugin_core/flutter_ota_kit_plugin_core.dart';
|
|
7
7
|
|
|
8
8
|
import 'supabase_client_adapter.dart';
|
|
9
9
|
import 'supabase_client_http.dart';
|
|
@@ -151,11 +151,8 @@ class NodeStorageProfileImpl implements NodeStorageProfile {
|
|
|
151
151
|
}
|
|
152
152
|
|
|
153
153
|
await verifySigned(bucket: bucket, key: storageKey);
|
|
154
|
-
final fullPath = upload.data is Map
|
|
155
|
-
? (upload.data as Map)['fullPath'] as String?
|
|
156
|
-
: null;
|
|
157
154
|
return {
|
|
158
|
-
'storageUri': 'supabase-storage://$
|
|
155
|
+
'storageUri': 'supabase-storage://$bucketName/$storageKey',
|
|
159
156
|
};
|
|
160
157
|
}
|
|
161
158
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
name:
|
|
2
|
-
description: Supabase plugin for
|
|
1
|
+
name: flutter_ota_kit_supabase
|
|
2
|
+
description: Supabase plugin for flutter_ota_kit — database + storage backends.
|
|
3
3
|
version: 0.1.0
|
|
4
4
|
publish_to: none
|
|
5
5
|
|
|
@@ -7,9 +7,9 @@ environment:
|
|
|
7
7
|
sdk: ">=3.3.0 <4.0.0"
|
|
8
8
|
|
|
9
9
|
dependencies:
|
|
10
|
-
|
|
10
|
+
flutter_ota_kit_core:
|
|
11
11
|
path: ../../packages/core
|
|
12
|
-
|
|
12
|
+
flutter_ota_kit_plugin_core:
|
|
13
13
|
path: ../../plugins/plugin-core
|
|
14
14
|
http: ^1.2.0
|
|
15
15
|
supabase: ^2.14.0
|
|
@@ -6,12 +6,12 @@
|
|
|
6
6
|
/// plugin, plus a configurable storage bucket used by the storage plugin.
|
|
7
7
|
library;
|
|
8
8
|
|
|
9
|
-
import 'package:
|
|
10
|
-
import 'package:
|
|
9
|
+
import 'package:flutter_ota_kit_core/flutter_ota_kit_core.dart';
|
|
10
|
+
import 'package:flutter_ota_kit_plugin_core/flutter_ota_kit_plugin_core.dart';
|
|
11
11
|
|
|
12
|
-
import 'package:
|
|
13
|
-
import 'package:
|
|
14
|
-
import 'package:
|
|
12
|
+
import 'package:flutter_ota_kit_supabase/src/supabase_bundle_mapper.dart';
|
|
13
|
+
import 'package:flutter_ota_kit_supabase/src/supabase_client_adapter.dart';
|
|
14
|
+
import 'package:flutter_ota_kit_supabase/src/types.dart';
|
|
15
15
|
|
|
16
16
|
// ---------------------------------------------------------------------------
|
|
17
17
|
// In-memory row store
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import 'package:
|
|
2
|
-
import 'package:
|
|
3
|
-
import 'package:
|
|
1
|
+
import 'package:flutter_ota_kit_core/flutter_ota_kit_core.dart';
|
|
2
|
+
import 'package:flutter_ota_kit_supabase/src/supabase_bundle_mapper.dart';
|
|
3
|
+
import 'package:flutter_ota_kit_supabase/src/types.dart';
|
|
4
4
|
import 'package:test/test.dart';
|
|
5
5
|
|
|
6
6
|
Bundle _makeBundle({List<BundlePatchArtifact> patches = const []}) => Bundle(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import 'package:
|
|
2
|
-
import 'package:
|
|
3
|
-
import 'package:
|
|
1
|
+
import 'package:flutter_ota_kit_core/flutter_ota_kit_core.dart';
|
|
2
|
+
import 'package:flutter_ota_kit_plugin_core/flutter_ota_kit_plugin_core.dart';
|
|
3
|
+
import 'package:flutter_ota_kit_supabase/flutter_ota_kit_supabase.dart';
|
|
4
4
|
import 'package:test/test.dart';
|
|
5
5
|
|
|
6
6
|
import 'mock_supabase_client.dart';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import 'dart:io' as io;
|
|
2
2
|
|
|
3
|
-
import 'package:
|
|
4
|
-
import 'package:
|
|
3
|
+
import 'package:flutter_ota_kit_plugin_core/flutter_ota_kit_plugin_core.dart';
|
|
4
|
+
import 'package:flutter_ota_kit_supabase/flutter_ota_kit_supabase.dart';
|
|
5
5
|
import 'package:test/test.dart';
|
|
6
6
|
|
|
7
7
|
import 'mock_supabase_client.dart';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# AWS migrations
|
|
2
|
+
|
|
3
|
+
The AWS backend stores bundle metadata as JSON in S3 (blob database), not in a
|
|
4
|
+
relational database. There are **no SQL migrations** to apply — the bucket and
|
|
5
|
+
object prefix are created on first `deploy`.
|
|
6
|
+
|
|
7
|
+
If you front downloads with CloudFront, provision the distribution separately.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
-- Migration number: 0001 2025-01-27T08:37:50.374Z
|
|
2
|
+
-- HotUpdater.bundles
|
|
3
|
+
|
|
4
|
+
CREATE TABLE bundles (
|
|
5
|
+
id TEXT PRIMARY KEY,
|
|
6
|
+
platform TEXT NOT NULL CHECK (platform IN ('ios', 'android')),
|
|
7
|
+
target_app_version TEXT NOT NULL,
|
|
8
|
+
should_force_update INTEGER NOT NULL CHECK (should_force_update IN (0, 1)),
|
|
9
|
+
enabled INTEGER NOT NULL CHECK (enabled IN (0, 1)),
|
|
10
|
+
file_url TEXT NOT NULL,
|
|
11
|
+
file_hash TEXT NOT NULL,
|
|
12
|
+
git_commit_hash TEXT,
|
|
13
|
+
message TEXT
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
CREATE INDEX bundles_target_app_version_idx ON bundles(target_app_version);
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
-- Migration number: 0003 2025-05-18T16:25:12.486Z
|
|
2
|
+
-- HotUpdater.bundles
|
|
3
|
+
|
|
4
|
+
ALTER TABLE bundles ADD COLUMN fingerprint_hash TEXT;
|
|
5
|
+
ALTER TABLE bundles ADD COLUMN storage_uri TEXT;
|
|
6
|
+
ALTER TABLE bundles ADD COLUMN metadata JSONB DEFAULT '{}';
|
|
7
|
+
|
|
8
|
+
UPDATE bundles
|
|
9
|
+
SET storage_uri = 'r2://%%BUCKET_NAME%%/' || id || '/bundle.zip'
|
|
10
|
+
WHERE storage_uri IS NULL;
|
|
11
|
+
|
|
12
|
+
CREATE TABLE bundles_temp (
|
|
13
|
+
id TEXT PRIMARY KEY,
|
|
14
|
+
platform TEXT NOT NULL,
|
|
15
|
+
should_force_update INTEGER NOT NULL,
|
|
16
|
+
enabled INTEGER NOT NULL,
|
|
17
|
+
file_hash TEXT NOT NULL,
|
|
18
|
+
git_commit_hash TEXT,
|
|
19
|
+
message TEXT,
|
|
20
|
+
channel TEXT NOT NULL DEFAULT 'production',
|
|
21
|
+
storage_uri TEXT NOT NULL,
|
|
22
|
+
target_app_version TEXT,
|
|
23
|
+
fingerprint_hash TEXT,
|
|
24
|
+
metadata JSONB DEFAULT '{}',
|
|
25
|
+
CHECK ((target_app_version IS NOT NULL) OR (fingerprint_hash IS NOT NULL))
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
INSERT INTO bundles_temp
|
|
29
|
+
SELECT id, platform, should_force_update, enabled, file_hash, git_commit_hash, message, channel, storage_uri, target_app_version, fingerprint_hash, metadata
|
|
30
|
+
FROM bundles;
|
|
31
|
+
|
|
32
|
+
DROP TABLE bundles;
|
|
33
|
+
|
|
34
|
+
ALTER TABLE bundles_temp RENAME TO bundles;
|
|
35
|
+
|
|
36
|
+
CREATE INDEX bundles_target_app_version_idx ON bundles(target_app_version);
|
|
37
|
+
CREATE INDEX bundles_fingerprint_hash_idx ON bundles(fingerprint_hash);
|
|
38
|
+
CREATE INDEX bundles_channel_idx ON bundles(channel);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
-- Migration number: 0004 2025-12-21T00:00:00.000Z
|
|
2
|
+
|
|
3
|
+
-- HotUpdater.bundles
|
|
4
|
+
|
|
5
|
+
ALTER TABLE bundles ADD COLUMN rollout_cohort_count INTEGER DEFAULT 1000
|
|
6
|
+
CHECK (rollout_cohort_count >= 0 AND rollout_cohort_count <= 1000);
|
|
7
|
+
|
|
8
|
+
CREATE INDEX IF NOT EXISTS bundles_rollout_idx ON bundles(rollout_cohort_count);
|
|
9
|
+
|
|
10
|
+
-- SQLite doesn't have array type, store as JSON text
|
|
11
|
+
ALTER TABLE bundles ADD COLUMN target_cohorts TEXT;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
-- Migration number: 0005 2026-04-22T00:00:00.000Z
|
|
2
|
+
|
|
3
|
+
-- HotUpdater.bundle_artifact_columns
|
|
4
|
+
|
|
5
|
+
ALTER TABLE bundles ADD COLUMN manifest_storage_uri TEXT;
|
|
6
|
+
ALTER TABLE bundles ADD COLUMN manifest_file_hash TEXT;
|
|
7
|
+
ALTER TABLE bundles ADD COLUMN asset_base_storage_uri TEXT;
|
|
8
|
+
|
|
9
|
+
CREATE TABLE bundle_patches (
|
|
10
|
+
id TEXT PRIMARY KEY,
|
|
11
|
+
bundle_id TEXT NOT NULL,
|
|
12
|
+
base_bundle_id TEXT NOT NULL,
|
|
13
|
+
base_file_hash TEXT NOT NULL,
|
|
14
|
+
patch_file_hash TEXT NOT NULL,
|
|
15
|
+
patch_storage_uri TEXT NOT NULL,
|
|
16
|
+
order_index INTEGER NOT NULL DEFAULT 0,
|
|
17
|
+
FOREIGN KEY (bundle_id) REFERENCES bundles(id) ON DELETE CASCADE,
|
|
18
|
+
FOREIGN KEY (base_bundle_id) REFERENCES bundles(id) ON DELETE CASCADE
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
CREATE INDEX IF NOT EXISTS bundle_patches_bundle_id_idx
|
|
22
|
+
ON bundle_patches(bundle_id);
|
|
23
|
+
CREATE INDEX IF NOT EXISTS bundle_patches_base_bundle_id_idx
|
|
24
|
+
ON bundle_patches(base_bundle_id);
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
-- HotUpdater.bundles
|
|
2
|
+
|
|
3
|
+
CREATE TABLE bundles (
|
|
4
|
+
id TEXT PRIMARY KEY,
|
|
5
|
+
platform TEXT NOT NULL CHECK (platform IN ('ios', 'android')),
|
|
6
|
+
target_app_version TEXT,
|
|
7
|
+
should_force_update INTEGER NOT NULL CHECK (should_force_update IN (0, 1)),
|
|
8
|
+
enabled INTEGER NOT NULL CHECK (enabled IN (0, 1)),
|
|
9
|
+
file_hash TEXT NOT NULL,
|
|
10
|
+
git_commit_hash TEXT,
|
|
11
|
+
message TEXT,
|
|
12
|
+
channel TEXT NOT NULL DEFAULT 'production',
|
|
13
|
+
storage_uri TEXT NOT NULL,
|
|
14
|
+
fingerprint_hash TEXT,
|
|
15
|
+
metadata JSONB DEFAULT '{}',
|
|
16
|
+
manifest_storage_uri TEXT,
|
|
17
|
+
manifest_file_hash TEXT,
|
|
18
|
+
asset_base_storage_uri TEXT,
|
|
19
|
+
rollout_cohort_count INTEGER DEFAULT 1000
|
|
20
|
+
CHECK (rollout_cohort_count >= 0 AND rollout_cohort_count <= 1000),
|
|
21
|
+
target_cohorts TEXT,
|
|
22
|
+
CHECK ((target_app_version IS NOT NULL) OR (fingerprint_hash IS NOT NULL))
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
CREATE TABLE bundle_patches (
|
|
26
|
+
id TEXT PRIMARY KEY,
|
|
27
|
+
bundle_id TEXT NOT NULL,
|
|
28
|
+
base_bundle_id TEXT NOT NULL,
|
|
29
|
+
base_file_hash TEXT NOT NULL,
|
|
30
|
+
patch_file_hash TEXT NOT NULL,
|
|
31
|
+
patch_storage_uri TEXT NOT NULL,
|
|
32
|
+
order_index INTEGER NOT NULL DEFAULT 0,
|
|
33
|
+
FOREIGN KEY (bundle_id) REFERENCES bundles(id) ON DELETE CASCADE,
|
|
34
|
+
FOREIGN KEY (base_bundle_id) REFERENCES bundles(id) ON DELETE CASCADE
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
CREATE INDEX bundles_target_app_version_idx ON bundles(target_app_version);
|
|
38
|
+
CREATE INDEX bundles_fingerprint_hash_idx ON bundles(fingerprint_hash);
|
|
39
|
+
CREATE INDEX bundles_channel_idx ON bundles(channel);
|
|
40
|
+
CREATE INDEX bundles_rollout_idx ON bundles(rollout_cohort_count);
|
|
41
|
+
CREATE INDEX bundle_patches_bundle_id_idx ON bundle_patches(bundle_id);
|
|
42
|
+
CREATE INDEX bundle_patches_base_bundle_id_idx ON bundle_patches(base_bundle_id);
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
-- HotUpdater.bundles
|
|
2
|
+
|
|
3
|
+
CREATE TYPE platforms AS ENUM ('ios', 'android');
|
|
4
|
+
|
|
5
|
+
CREATE TABLE bundles (
|
|
6
|
+
id uuid PRIMARY KEY,
|
|
7
|
+
platform platforms NOT NULL,
|
|
8
|
+
should_force_update boolean NOT NULL,
|
|
9
|
+
enabled boolean NOT NULL,
|
|
10
|
+
file_hash text NOT NULL,
|
|
11
|
+
git_commit_hash text,
|
|
12
|
+
message text,
|
|
13
|
+
channel text NOT NULL DEFAULT 'production',
|
|
14
|
+
storage_uri text NOT NULL,
|
|
15
|
+
target_app_version text,
|
|
16
|
+
fingerprint_hash text,
|
|
17
|
+
CONSTRAINT check_version_or_fingerprint CHECK (
|
|
18
|
+
(target_app_version IS NOT NULL) OR (fingerprint_hash IS NOT NULL)
|
|
19
|
+
),
|
|
20
|
+
metadata jsonb DEFAULT '{}'::jsonb,
|
|
21
|
+
manifest_storage_uri text,
|
|
22
|
+
manifest_file_hash text,
|
|
23
|
+
asset_base_storage_uri text,
|
|
24
|
+
rollout_cohort_count INTEGER DEFAULT 1000
|
|
25
|
+
CHECK (rollout_cohort_count >= 0 AND rollout_cohort_count <= 1000),
|
|
26
|
+
target_cohorts TEXT[]
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
CREATE TABLE bundle_patches (
|
|
30
|
+
id text PRIMARY KEY,
|
|
31
|
+
bundle_id uuid NOT NULL REFERENCES bundles(id) ON DELETE CASCADE,
|
|
32
|
+
base_bundle_id uuid NOT NULL REFERENCES bundles(id) ON DELETE CASCADE,
|
|
33
|
+
base_file_hash text NOT NULL,
|
|
34
|
+
patch_file_hash text NOT NULL,
|
|
35
|
+
patch_storage_uri text NOT NULL,
|
|
36
|
+
order_index integer NOT NULL DEFAULT 0
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
CREATE INDEX bundles_target_app_version_idx ON bundles(target_app_version);
|
|
40
|
+
CREATE INDEX bundles_fingerprint_hash_idx ON bundles(fingerprint_hash);
|
|
41
|
+
CREATE INDEX bundles_channel_idx ON bundles(channel);
|
|
42
|
+
CREATE INDEX bundles_rollout_idx ON bundles(rollout_cohort_count);
|
|
43
|
+
CREATE INDEX bundles_target_cohorts_idx ON bundles USING GIN (target_cohorts);
|
|
44
|
+
CREATE INDEX bundle_patches_bundle_id_idx ON bundle_patches(bundle_id);
|
|
45
|
+
CREATE INDEX bundle_patches_base_bundle_id_idx ON bundle_patches(base_bundle_id);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
-- HotUpdater.get_target_app_version_list
|
|
2
|
+
|
|
3
|
+
CREATE OR REPLACE FUNCTION get_target_app_version_list (
|
|
4
|
+
app_platform platforms,
|
|
5
|
+
min_bundle_id uuid
|
|
6
|
+
)
|
|
7
|
+
RETURNS TABLE (
|
|
8
|
+
target_app_version text
|
|
9
|
+
)
|
|
10
|
+
LANGUAGE plpgsql
|
|
11
|
+
AS
|
|
12
|
+
$$
|
|
13
|
+
BEGIN
|
|
14
|
+
RETURN QUERY
|
|
15
|
+
SELECT b.target_app_version
|
|
16
|
+
FROM bundles b
|
|
17
|
+
WHERE b.platform = app_platform
|
|
18
|
+
AND b.id >= min_bundle_id
|
|
19
|
+
GROUP BY b.target_app_version;
|
|
20
|
+
END;
|
|
21
|
+
$$;
|