@_nazmiforreal/flutter-ota 0.1.26 → 0.1.28
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 +112 -18
- package/bin/flutter-ota-linux-x64 +0 -0
- package/bin/flutter-ota.js +12 -11
- package/dart-src/packages/cli-tools/README.md +146 -2
- package/dart-src/packages/cli-tools/lib/flutter_ota_kit_cli.dart +46 -13
- package/dart-src/packages/cli-tools/lib/src/backend.dart +6 -6
- package/dart-src/packages/cli-tools/lib/src/commands/build.dart +2 -0
- package/dart-src/packages/cli-tools/lib/src/commands/bundle.dart +7 -7
- package/dart-src/packages/cli-tools/lib/src/commands/deploy.dart +4 -1
- package/dart-src/packages/cli-tools/lib/src/commands/init.dart +36 -8
- package/dart-src/packages/cli-tools/lib/src/commands/pocketbase.dart +1 -1
- package/dart-src/packages/cli-tools/lib/src/commands/rollback.dart +1 -1
- package/dart-src/packages/cli-tools/lib/src/config.dart +5 -5
- package/dart-src/packages/cli-tools/lib/src/operations.dart +2 -2
- package/dart-src/packages/cli-tools/pubspec.yaml +8 -21
- package/dart-src/packages/cli-tools/test/backends_test.dart +3 -3
- package/dart-src/packages/cli-tools/test/cli_test.dart +1 -1
- 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_pocketbase_client.dart +4 -1
- package/dart-src/packages/cli-tools/test/mocks/mock_postgres_client.dart +2 -2
- package/dart-src/packages/cli-tools/test/pocketbase_smoke_test.dart +1 -1
- package/dart-src/root/README.md +334 -0
- package/dart-src/root/analysis_options.yaml +21 -0
- package/dart-src/root/android/build.gradle +116 -0
- package/dart-src/root/android/consumer-rules.pro +23 -0
- package/dart-src/root/android/settings.gradle +1 -0
- package/dart-src/root/android/src/main/AndroidManifest.xml +21 -0
- package/dart-src/root/android/src/main/kotlin/com/flutter_patcher/flutter_patcher/ApplyResult.kt +52 -0
- package/dart-src/root/android/src/main/kotlin/com/flutter_patcher/flutter_patcher/BlacklistStore.kt +154 -0
- package/dart-src/root/android/src/main/kotlin/com/flutter_patcher/flutter_patcher/BootDiagnosticStore.kt +150 -0
- package/dart-src/root/android/src/main/kotlin/com/flutter_patcher/flutter_patcher/CrashGuard.kt +271 -0
- package/dart-src/root/android/src/main/kotlin/com/flutter_patcher/flutter_patcher/FlutterPatcherApplication.kt +201 -0
- package/dart-src/root/android/src/main/kotlin/com/flutter_patcher/flutter_patcher/FlutterPatcherAutoInitProvider.kt +93 -0
- package/dart-src/root/android/src/main/kotlin/com/flutter_patcher/flutter_patcher/FlutterPatcherPlugin.kt +245 -0
- package/dart-src/root/android/src/main/kotlin/com/flutter_patcher/flutter_patcher/LoaderHook.kt +298 -0
- package/dart-src/root/android/src/main/kotlin/com/flutter_patcher/flutter_patcher/PatchManager.kt +1579 -0
- package/dart-src/root/android/src/main/kotlin/com/flutter_patcher/flutter_patcher/PatcherConfig.kt +173 -0
- package/dart-src/root/android/src/main/kotlin/com/flutter_patcher/flutter_patcher/SignatureVerifier.kt +177 -0
- package/dart-src/root/android/src/test/kotlin/com/flutter_patcher/flutter_patcher/CrashGuardTest.kt +61 -0
- package/dart-src/root/android/src/test/kotlin/com/flutter_patcher/flutter_patcher/LoaderHookTest.kt +25 -0
- package/dart-src/root/android/src/test/kotlin/com/flutter_patcher/flutter_patcher/PatchManagerTest.kt +401 -0
- package/dart-src/root/android/src/test/kotlin/com/flutter_patcher/flutter_patcher/PatcherConfigTest.kt +30 -0
- package/dart-src/root/bin/pack.dart +182 -0
- package/dart-src/root/lib/flutter_ota_kit.dart +1170 -0
- package/dart-src/root/lib/src/app_version_resolver.dart +36 -0
- package/dart-src/root/lib/src/aws_update_source.dart +97 -0
- package/dart-src/root/lib/src/blacklist.dart +54 -0
- package/dart-src/root/lib/src/boot_diagnostic.dart +138 -0
- package/dart-src/root/lib/src/cloudflare_update_source.dart +97 -0
- package/dart-src/root/lib/src/flutter_ota_app.dart +69 -0
- package/dart-src/root/lib/src/io.dart +48 -0
- package/dart-src/root/lib/src/io_stub.dart +19 -0
- package/dart-src/root/lib/src/ota_progress_overlay.dart +1186 -0
- package/dart-src/root/lib/src/pack/pack.dart +434 -0
- package/dart-src/root/lib/src/patch_info.dart +12 -0
- package/dart-src/root/lib/src/patcher_channel.dart +160 -0
- package/dart-src/{plugins/aws/lib → root/lib/src/pkg/aws}/src/aws_database.dart +1 -1
- package/dart-src/{plugins/aws/lib → root/lib/src/pkg/aws}/src/aws_s3_client.dart +1 -1
- package/dart-src/{plugins/aws/lib → root/lib/src/pkg/aws}/src/aws_storage.dart +1 -1
- package/dart-src/{plugins/aws/lib → root/lib/src/pkg/aws}/src/aws_storage_profile.dart +1 -1
- package/dart-src/{plugins/aws/lib → root/lib/src/pkg/aws}/src/with_cloudfront_signed_url.dart +1 -1
- package/dart-src/root/lib/src/pkg/client/flutter_ota_kit_client.dart +1 -0
- package/dart-src/root/lib/src/pkg/client/src/server_update_source.dart +46 -0
- package/dart-src/{plugins/cloudflare/lib → root/lib/src/pkg/cloudflare}/src/cloudflare_worker_database.dart +1 -1
- package/dart-src/{plugins/cloudflare/lib → root/lib/src/pkg/cloudflare}/src/d1_build_where.dart +1 -1
- package/dart-src/{plugins/cloudflare/lib → root/lib/src/pkg/cloudflare}/src/d1_bundle_mapper.dart +3 -3
- package/dart-src/{plugins/cloudflare/lib → root/lib/src/pkg/cloudflare}/src/d1_database.dart +1 -1
- package/dart-src/{plugins/cloudflare/lib → root/lib/src/pkg/cloudflare}/src/d1_database_plugin.dart +2 -2
- package/dart-src/{plugins/cloudflare/lib → root/lib/src/pkg/cloudflare}/src/r2_s3_client.dart +1 -1
- package/dart-src/{plugins/cloudflare/lib → root/lib/src/pkg/cloudflare}/src/r2_storage.dart +1 -1
- package/dart-src/{plugins/cloudflare/lib → root/lib/src/pkg/cloudflare}/src/r2_storage_profile.dart +1 -1
- package/dart-src/{packages/core/lib → root/lib/src/pkg/core}/src/status.dart +1 -1
- package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/flutter_ota_kit_plugin_core.dart +1 -1
- package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/create_blob_database_plugin.dart +1 -1
- package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/filter_compatible_app_versions.dart +1 -1
- package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/get_update_info.dart +1 -1
- package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/request_update_bundle_state.dart +1 -1
- package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/resolve_update_info_from_bundles.dart +1 -1
- package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/types.dart +2 -2
- package/dart-src/{plugins/pocketbase/lib → root/lib/src/pkg/pocketbase}/src/pocketbase_bundle_mapper.dart +2 -2
- package/dart-src/{plugins/pocketbase/lib → root/lib/src/pkg/pocketbase}/src/pocketbase_database.dart +26 -15
- package/dart-src/{plugins/pocketbase/lib → root/lib/src/pkg/pocketbase}/src/pocketbase_storage.dart +1 -1
- package/dart-src/{plugins/postgres/lib → root/lib/src/pkg/postgres}/src/postgres_bundle_mapper.dart +2 -2
- package/dart-src/{plugins/postgres/lib → root/lib/src/pkg/postgres}/src/postgres_database.dart +2 -2
- package/dart-src/{plugins/postgres/lib → root/lib/src/pkg/postgres}/src/postgres_get_update_info.dart +2 -2
- package/dart-src/{plugins/postgres/lib → root/lib/src/pkg/postgres}/src/postgres_storage.dart +1 -1
- package/dart-src/{plugins/postgres/lib → root/lib/src/pkg/postgres}/src/postgres_types.dart +1 -1
- package/dart-src/{plugins/supabase/lib → root/lib/src/pkg/supabase}/src/supabase_bundle_mapper.dart +2 -2
- package/dart-src/{plugins/supabase/lib → root/lib/src/pkg/supabase}/src/supabase_database.dart +2 -2
- package/dart-src/{plugins/supabase/lib → root/lib/src/pkg/supabase}/src/supabase_edge_function_database.dart +1 -1
- package/dart-src/{plugins/supabase/lib → root/lib/src/pkg/supabase}/src/supabase_edge_function_storage.dart +1 -1
- package/dart-src/{plugins/supabase/lib → root/lib/src/pkg/supabase}/src/supabase_storage.dart +1 -1
- package/dart-src/root/lib/src/pocketbase_update_source.dart +107 -0
- package/dart-src/root/lib/src/postgres_update_source.dart +95 -0
- package/dart-src/root/lib/src/shared_update_check.dart +131 -0
- package/dart-src/root/lib/src/supabase_update_source.dart +93 -0
- package/dart-src/root/pubspec.yaml +54 -0
- package/package.json +1 -1
- package/scripts/postinstall.js +17 -13
- package/scripts/vendor.sh +22 -7
- package/dart-src/packages/core/CHANGELOG.md +0 -21
- package/dart-src/packages/core/README.md +0 -23
- package/dart-src/packages/core/example/lib/main.dart +0 -69
- package/dart-src/packages/core/pubspec.yaml +0 -13
- package/dart-src/packages/core/test/rollout_test.dart +0 -135
- package/dart-src/packages/core/test/semver_test.dart +0 -55
- package/dart-src/packages/core/test/semver_vectors.json +0 -1
- package/dart-src/packages/core/test/types_test.dart +0 -131
- package/dart-src/packages/core/test/uuid_test.dart +0 -40
- package/dart-src/packages/core/tool/dbg.dart +0 -7
- package/dart-src/plugins/aws/.gitkeep +0 -0
- package/dart-src/plugins/aws/CHANGELOG.md +0 -23
- package/dart-src/plugins/aws/LICENSE +0 -21
- package/dart-src/plugins/aws/README.md +0 -28
- package/dart-src/plugins/aws/example/lib/main.dart +0 -60
- package/dart-src/plugins/aws/pubspec.yaml +0 -30
- package/dart-src/plugins/aws/test/aws_database_test.dart +0 -161
- package/dart-src/plugins/aws/test/aws_storage_test.dart +0 -73
- package/dart-src/plugins/aws/test/mock_aws_s3_client.dart +0 -78
- package/dart-src/plugins/cloudflare/.gitkeep +0 -0
- package/dart-src/plugins/cloudflare/CHANGELOG.md +0 -23
- package/dart-src/plugins/cloudflare/LICENSE +0 -21
- package/dart-src/plugins/cloudflare/README.md +0 -25
- package/dart-src/plugins/cloudflare/example/lib/main.dart +0 -62
- package/dart-src/plugins/cloudflare/migrations/0001_hot-updater_init.sql +0 -16
- package/dart-src/plugins/cloudflare/migrations/0002_hot-updater_0.13.0.sql +0 -8
- package/dart-src/plugins/cloudflare/migrations/0003_hot-updater_0.18.0.sql +0 -38
- package/dart-src/plugins/cloudflare/migrations/0004_hot-updater_0.29.0.sql +0 -11
- package/dart-src/plugins/cloudflare/migrations/0005_hot-updater_0.31.0.sql +0 -24
- package/dart-src/plugins/cloudflare/pubspec.yaml +0 -28
- package/dart-src/plugins/cloudflare/sql/bundles.sql +0 -42
- package/dart-src/plugins/cloudflare/test/cloudflare_worker_database_test.dart +0 -126
- package/dart-src/plugins/cloudflare/test/d1_bundle_mapper_test.dart +0 -106
- package/dart-src/plugins/cloudflare/test/d1_database_test.dart +0 -200
- package/dart-src/plugins/cloudflare/test/mock_d1_client.dart +0 -261
- package/dart-src/plugins/cloudflare/test/mock_r2_client.dart +0 -78
- package/dart-src/plugins/cloudflare/test/r2_storage_test.dart +0 -74
- package/dart-src/plugins/plugin-core/CHANGELOG.md +0 -20
- package/dart-src/plugins/plugin-core/LICENSE +0 -21
- package/dart-src/plugins/plugin-core/README.md +0 -21
- package/dart-src/plugins/plugin-core/example/lib/main.dart +0 -61
- package/dart-src/plugins/plugin-core/pubspec.yaml +0 -23
- package/dart-src/plugins/plugin-core/test/asset_storage_layout_test.dart +0 -170
- package/dart-src/plugins/plugin-core/test/bundle_unit_of_work_store_test.dart +0 -74
- package/dart-src/plugins/plugin-core/test/bundle_unit_of_work_test.dart +0 -345
- package/dart-src/plugins/plugin-core/test/create_blob_database_plugin_test.dart +0 -843
- package/dart-src/plugins/plugin-core/test/create_database_plugin_test.dart +0 -298
- package/dart-src/plugins/plugin-core/test/create_storage_plugin_test.dart +0 -195
- package/dart-src/plugins/plugin-core/test/generate_min_bundle_id_test.dart +0 -56
- package/dart-src/plugins/plugin-core/test/get_update_info_test.dart +0 -1589
- package/dart-src/plugins/plugin-core/test/helpers_test.dart +0 -283
- package/dart-src/plugins/plugin-core/test/query_bundles_test.dart +0 -202
- package/dart-src/plugins/plugin-core/test/request_update_bundle_state_test.dart +0 -86
- package/dart-src/plugins/plugin-core/test/uuidv7_test.dart +0 -88
- package/dart-src/plugins/pocketbase/CHANGELOG.md +0 -23
- package/dart-src/plugins/pocketbase/LICENSE +0 -21
- package/dart-src/plugins/pocketbase/README.md +0 -54
- package/dart-src/plugins/pocketbase/example/lib/main.dart +0 -62
- package/dart-src/plugins/pocketbase/pubspec.yaml +0 -26
- package/dart-src/plugins/pocketbase/test/pb_uri_test.dart +0 -12
- package/dart-src/plugins/postgres/.gitkeep +0 -0
- package/dart-src/plugins/postgres/CHANGELOG.md +0 -23
- package/dart-src/plugins/postgres/LICENSE +0 -21
- package/dart-src/plugins/postgres/README.md +0 -29
- package/dart-src/plugins/postgres/example/lib/main.dart +0 -67
- package/dart-src/plugins/postgres/pubspec.yaml +0 -26
- package/dart-src/plugins/postgres/sql/bundles.sql +0 -45
- package/dart-src/plugins/postgres/sql/get_target_app_version_list.sql +0 -21
- package/dart-src/plugins/postgres/sql/get_update_info.spec.ts +0 -171
- package/dart-src/plugins/postgres/sql/get_update_info_by_app_version.sql +0 -126
- package/dart-src/plugins/postgres/sql/get_update_info_by_fingerprint_hash.sql +0 -125
- package/dart-src/plugins/postgres/sql/hash_user_id.sql +0 -30
- package/dart-src/plugins/postgres/sql/is_device_eligible.sql +0 -237
- package/dart-src/plugins/postgres/sql/prepareSql.ts +0 -11
- package/dart-src/plugins/postgres/test/mock_postgres_client.dart +0 -320
- package/dart-src/plugins/postgres/test/postgres_bundle_mapper_test.dart +0 -139
- package/dart-src/plugins/postgres/test/postgres_database_test.dart +0 -210
- package/dart-src/plugins/postgres/test/postgres_storage_runtime_test.dart +0 -60
- package/dart-src/plugins/supabase/CHANGELOG.md +0 -24
- package/dart-src/plugins/supabase/LICENSE +0 -21
- package/dart-src/plugins/supabase/README.md +0 -53
- package/dart-src/plugins/supabase/example/lib/main.dart +0 -63
- package/dart-src/plugins/supabase/pubspec.yaml +0 -27
- package/dart-src/plugins/supabase/supabase/edge-functions/index.ts +0 -44
- package/dart-src/plugins/supabase/supabase/edge-functions/runtime.docker.integration.spec.ts +0 -968
- package/dart-src/plugins/supabase/supabase/migrations/20250103114225_init.sql +0 -232
- package/dart-src/plugins/supabase/supabase/migrations/20250314000000_hot-updater_0.13.0.sql +0 -137
- package/dart-src/plugins/supabase/supabase/migrations/20250516000000_hot-updater_0.18.0.sql +0 -206
- package/dart-src/plugins/supabase/supabase/migrations/20251014000000_hot-updater_0.21.0.sql +0 -186
- package/dart-src/plugins/supabase/supabase/migrations/20260401000000_hot-updater_0.29.0.sql +0 -505
- package/dart-src/plugins/supabase/supabase/migrations/20260414000000_hot-updater_0.30.0.sql +0 -50
- package/dart-src/plugins/supabase/supabase/migrations/20260422000000_hot-updater_0.31.0.sql +0 -20
- package/dart-src/plugins/supabase/supabase/migrations/20260520014100_hot-updater_rls.sql +0 -75
- package/dart-src/plugins/supabase/test/mock_supabase_client.dart +0 -654
- package/dart-src/plugins/supabase/test/supabase_bundle_mapper_test.dart +0 -115
- package/dart-src/plugins/supabase/test/supabase_database_test.dart +0 -198
- package/dart-src/plugins/supabase/test/supabase_storage_test.dart +0 -168
- /package/dart-src/{packages/core → root}/LICENSE +0 -0
- /package/dart-src/{plugins/aws/lib → root/lib/src/pkg/aws}/flutter_ota_kit_aws.dart +0 -0
- /package/dart-src/{plugins/aws/lib → root/lib/src/pkg/aws}/src/aws_cloudfront_client.dart +0 -0
- /package/dart-src/{plugins/aws/lib → root/lib/src/pkg/aws}/src/aws_cloudfront_signer.dart +0 -0
- /package/dart-src/{plugins/aws/lib → root/lib/src/pkg/aws}/src/aws_config.dart +0 -0
- /package/dart-src/{plugins/aws/lib → root/lib/src/pkg/aws}/src/aws_ssm_client.dart +0 -0
- /package/dart-src/{plugins/cloudflare/lib → root/lib/src/pkg/cloudflare}/flutter_ota_kit_cloudflare.dart +0 -0
- /package/dart-src/{plugins/cloudflare/lib → root/lib/src/pkg/cloudflare}/src/d1_client.dart +0 -0
- /package/dart-src/{plugins/cloudflare/lib → root/lib/src/pkg/cloudflare}/src/d1_config.dart +0 -0
- /package/dart-src/{plugins/cloudflare/lib → root/lib/src/pkg/cloudflare}/src/r2_config.dart +0 -0
- /package/dart-src/{packages/core/lib → root/lib/src/pkg/core}/flutter_ota_kit_core.dart +0 -0
- /package/dart-src/{packages/core/lib → root/lib/src/pkg/core}/src/app_update_info.dart +0 -0
- /package/dart-src/{packages/core/lib → root/lib/src/pkg/core}/src/bundle.dart +0 -0
- /package/dart-src/{packages/core/lib → root/lib/src/pkg/core}/src/bundle_artifacts.dart +0 -0
- /package/dart-src/{packages/core/lib → root/lib/src/pkg/core}/src/bundle_patch_artifact.dart +0 -0
- /package/dart-src/{packages/core/lib → root/lib/src/pkg/core}/src/changed_asset.dart +0 -0
- /package/dart-src/{packages/core/lib → root/lib/src/pkg/core}/src/get_bundles_args.dart +0 -0
- /package/dart-src/{packages/core/lib → root/lib/src/pkg/core}/src/metadata.dart +0 -0
- /package/dart-src/{packages/core/lib → root/lib/src/pkg/core}/src/patch_info.dart +0 -0
- /package/dart-src/{packages/core/lib → root/lib/src/pkg/core}/src/platform.dart +0 -0
- /package/dart-src/{packages/core/lib → root/lib/src/pkg/core}/src/rollout.dart +0 -0
- /package/dart-src/{packages/core/lib → root/lib/src/pkg/core}/src/semver.dart +0 -0
- /package/dart-src/{packages/core/lib → root/lib/src/pkg/core}/src/semver_range.dart +0 -0
- /package/dart-src/{packages/core/lib → root/lib/src/pkg/core}/src/semver_version.dart +0 -0
- /package/dart-src/{packages/core/lib → root/lib/src/pkg/core}/src/strategy.dart +0 -0
- /package/dart-src/{packages/core/lib → root/lib/src/pkg/core}/src/update_bundle_params.dart +0 -0
- /package/dart-src/{packages/core/lib → root/lib/src/pkg/core}/src/uuid.dart +0 -0
- /package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/asset_storage_layout.dart +0 -0
- /package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/bundle_helpers.dart +0 -0
- /package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/bundle_storage_layout.dart +0 -0
- /package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/bundle_unit_of_work.dart +0 -0
- /package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/bundle_unit_of_work_store.dart +0 -0
- /package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/calculate_pagination.dart +0 -0
- /package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/compression_format.dart +0 -0
- /package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/content_addressed_assets.dart +0 -0
- /package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/create_database_plugin.dart +0 -0
- /package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/create_storage_key_builder.dart +0 -0
- /package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/create_storage_plugin.dart +0 -0
- /package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/generate_min_bundle_id.dart +0 -0
- /package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/is_object.dart +0 -0
- /package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/legacy_asset_storage_layout.dart +0 -0
- /package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/paginate_bundles.dart +0 -0
- /package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/parse_storage_uri.dart +0 -0
- /package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/query_bundles.dart +0 -0
- /package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/storage_helpers.dart +0 -0
- /package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/storage_profile.dart +0 -0
- /package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/uuidv7.dart +0 -0
- /package/dart-src/{plugins/pocketbase/lib → root/lib/src/pkg/pocketbase}/flutter_ota_kit_pocketbase.dart +0 -0
- /package/dart-src/{plugins/pocketbase/lib → root/lib/src/pkg/pocketbase}/src/pocketbase_client.dart +0 -0
- /package/dart-src/{plugins/pocketbase/lib → root/lib/src/pkg/pocketbase}/src/pocketbase_config.dart +0 -0
- /package/dart-src/{plugins/postgres/lib → root/lib/src/pkg/postgres}/flutter_ota_kit_postgres.dart +0 -0
- /package/dart-src/{plugins/postgres/lib → root/lib/src/pkg/postgres}/src/postgres_client.dart +0 -0
- /package/dart-src/{plugins/postgres/lib → root/lib/src/pkg/postgres}/src/postgres_config.dart +0 -0
- /package/dart-src/{plugins/supabase/lib → root/lib/src/pkg/supabase}/edge.dart +0 -0
- /package/dart-src/{plugins/supabase/lib → root/lib/src/pkg/supabase}/flutter_ota_kit_supabase.dart +0 -0
- /package/dart-src/{plugins/supabase/lib → root/lib/src/pkg/supabase}/src/error_message.dart +0 -0
- /package/dart-src/{plugins/supabase/lib → root/lib/src/pkg/supabase}/src/supabase_client_adapter.dart +0 -0
- /package/dart-src/{plugins/supabase/lib → root/lib/src/pkg/supabase}/src/supabase_client_http.dart +0 -0
- /package/dart-src/{plugins/supabase/lib → root/lib/src/pkg/supabase}/src/supabase_config.dart +0 -0
- /package/dart-src/{plugins/supabase/lib → root/lib/src/pkg/supabase}/src/supabase_signed_url_batcher.dart +0 -0
- /package/dart-src/{plugins/supabase/lib → root/lib/src/pkg/supabase}/src/types.dart +0 -0
package/README.md
CHANGED
|
@@ -1,37 +1,131 @@
|
|
|
1
|
-
# flutter-ota
|
|
1
|
+
# flutter-ota
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@_nazmiforreal/flutter-ota)
|
|
4
|
+
[](https://github.com/HYPER12755/flutter-ota-kit/blob/main/LICENSE)
|
|
5
|
+
|
|
6
|
+
### The command line for [flutter_ota_kit](https://pub.dev/packages/flutter_ota_kit) — build patches, deploy them to your backend, and manage rollouts.
|
|
7
|
+
|
|
8
|
+
`flutter-ota` is the companion CLI for **flutter_ota_kit**, open-source OTA code
|
|
9
|
+
push for Flutter Android. Pack a release APK into a signed patch, upload it to
|
|
10
|
+
the backend **you** own (Supabase / Postgres / Cloudflare / AWS / PocketBase),
|
|
11
|
+
and manage channels, staged rollouts, and instant rollback — no store review, no
|
|
12
|
+
monthly bill.
|
|
13
|
+
|
|
14
|
+
> The runtime SDK your app depends on is the separate
|
|
15
|
+
> [`flutter_ota_kit`](https://pub.dev/packages/flutter_ota_kit) pub package.
|
|
16
|
+
|
|
17
|
+
---
|
|
4
18
|
|
|
5
19
|
## Install
|
|
6
20
|
|
|
7
21
|
```bash
|
|
8
22
|
npm i -g @_nazmiforreal/flutter-ota
|
|
23
|
+
flutter-ota --help
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
A prebuilt `linux-x64` binary ships in the package. On other platforms the CLI
|
|
27
|
+
compiles from bundled Dart source on first install, which needs the
|
|
28
|
+
[**Flutter SDK**](https://flutter.dev) (the CLI shares the `flutter_ota_kit`
|
|
29
|
+
Flutter package). If Flutter isn't available, build a binary once yourself:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
cd $(npm root -g)/@_nazmiforreal/flutter-ota/dart-src/packages/cli-tools
|
|
33
|
+
flutter pub get && dart compile exe bin/flutter_ota_kit.dart -o ../../bin/flutter-ota-<os>-<arch>
|
|
9
34
|
```
|
|
10
35
|
|
|
11
|
-
|
|
36
|
+
---
|
|
12
37
|
|
|
13
|
-
##
|
|
38
|
+
## The 60-second workflow
|
|
14
39
|
|
|
15
40
|
```bash
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
flutter-ota
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
41
|
+
# 1. Scaffold config + a setup helper for your backend
|
|
42
|
+
# (adds the latest flutter_ota_kit to your pubspec automatically)
|
|
43
|
+
flutter-ota init supabase # or: postgres | cloudflare | aws | pocketbase
|
|
44
|
+
|
|
45
|
+
# 2. Provision the backend (Supabase & PocketBase are fully automated)
|
|
46
|
+
flutter-ota migrate supabase
|
|
47
|
+
|
|
48
|
+
# 3. Build the release APK, then pack it into a device-ready patch
|
|
49
|
+
flutter build apk --release
|
|
50
|
+
flutter-ota build \
|
|
51
|
+
--apk build/app/outputs/flutter-apk/app-release.apk \
|
|
52
|
+
--version 1.0.1 \
|
|
53
|
+
--target-version-code 100
|
|
54
|
+
|
|
55
|
+
# 4. Sign + deploy it to a channel
|
|
56
|
+
flutter-ota deploy --source dist --channel production \
|
|
57
|
+
--target-app-version 1.0.0 --force -m "hotfix: crash on login"
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Devices pick up the patch on their next launch. Pull it back with:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
flutter-ota rollback --channel production
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Commands
|
|
69
|
+
|
|
70
|
+
| Command | What it does |
|
|
71
|
+
|---------|--------------|
|
|
72
|
+
| `init <backend>` | Scaffold config, `.env`, and `lib/flutter_ota_kit_setup.dart`; add the SDK dependency + `INTERNET` permission |
|
|
73
|
+
| `build` | Pack a release APK into `dist/patch.zip` (all ABIs by default) |
|
|
74
|
+
| `deploy` | Upload + register a bundle; sign it with `--key` |
|
|
75
|
+
| `bundle` | `list` / `show` / `delete` / `disable` / `enable` / `force` / `promote` / `update` |
|
|
76
|
+
| `channel` | `list` / `get` / `set` the live bundle per channel |
|
|
77
|
+
| `rollback` | Disable the latest enabled bundle (or roll back to a specific one) |
|
|
78
|
+
| `storage` | `list` / `delete` stored bundle objects |
|
|
79
|
+
| `migrate` | Provision the backend schema |
|
|
80
|
+
| `keys` | Generate an Ed25519 signing keypair |
|
|
81
|
+
| `fingerprint` | Compute a deterministic build fingerprint |
|
|
82
|
+
| `doctor` | Diagnose the environment + backend connectivity |
|
|
83
|
+
| `config` | `get` / `set` / `list` config values |
|
|
84
|
+
| `console` | Open the web console |
|
|
85
|
+
| `pocketbase` | Manage a local single-binary PocketBase backend |
|
|
86
|
+
|
|
87
|
+
Help works at every level, including nested subcommands:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
flutter-ota deploy --help
|
|
91
|
+
flutter-ota bundle list --help
|
|
92
|
+
flutter-ota pocketbase records list --help
|
|
23
93
|
```
|
|
24
94
|
|
|
25
|
-
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Backends
|
|
98
|
+
|
|
99
|
+
Select one with `--backend supabase|postgres|cloudflare|aws|pocketbase` (or set
|
|
100
|
+
`provider` in `.flutter_ota_kit/config.json`). Settings resolve with a clear
|
|
101
|
+
precedence:
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
explicit flag > environment variable > .flutter_ota_kit/config.json > default
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Config search order: `./.flutter_ota_kit/config.json`, then
|
|
108
|
+
`~/.flutter_ota_kit/config.json`. Secrets belong in your shell env or `.env`,
|
|
109
|
+
never in committed config.
|
|
110
|
+
|
|
111
|
+
| Backend | Provisioning |
|
|
112
|
+
|---------|--------------|
|
|
113
|
+
| **Supabase** | `migrate supabase` — SQL + storage bucket, fully automated |
|
|
114
|
+
| **PocketBase** | `pocketbase install` + `pocketbase serve` — single binary, schema auto-installed |
|
|
115
|
+
| **Postgres** | `migrate postgres` applies SQL migrations |
|
|
116
|
+
| **Cloudflare** | `migrate cloudflare` creates D1 + R2, runs SQL |
|
|
117
|
+
| **AWS** | No SQL — S3 bucket/prefix created on first `deploy` |
|
|
118
|
+
|
|
119
|
+
---
|
|
26
120
|
|
|
27
|
-
|
|
28
|
-
Each resolves its own env / `.flutter_ota_kit/config.json` (global: `~/.flutter_ota_kit/config.json`).
|
|
121
|
+
## Documentation
|
|
29
122
|
|
|
30
|
-
|
|
123
|
+
- [CLI Reference](https://github.com/HYPER12755/flutter-ota-kit/blob/main/doc/cli-reference.md)
|
|
124
|
+
- [Getting Started](https://github.com/HYPER12755/flutter-ota-kit/blob/main/doc/getting-started.md)
|
|
125
|
+
- [Backends](https://github.com/HYPER12755/flutter-ota-kit/blob/main/doc/backends.md)
|
|
126
|
+
- [Production Playbook](https://github.com/HYPER12755/flutter-ota-kit/blob/main/doc/production-playbook.md)
|
|
31
127
|
|
|
32
|
-
|
|
33
|
-
`rollback`, `channel` (list/get/set), `fingerprint`, `doctor`, `migrate`, `config`
|
|
34
|
-
(get/set/list), `keys`, `console`, `storage` (list/delete).
|
|
128
|
+
---
|
|
35
129
|
|
|
36
130
|
## License
|
|
37
131
|
|
|
Binary file
|
package/bin/flutter-ota.js
CHANGED
|
@@ -55,31 +55,32 @@ if (fs.existsSync(binPath)) {
|
|
|
55
55
|
chmodIfNeeded(binPath);
|
|
56
56
|
run(binPath, process.argv.slice(2));
|
|
57
57
|
} else if (
|
|
58
|
-
spawnSync('
|
|
58
|
+
spawnSync('flutter', ['--version'], { stdio: 'ignore' }).status === 0 &&
|
|
59
59
|
fs.existsSync(sourceEntry)
|
|
60
60
|
) {
|
|
61
|
-
//
|
|
62
|
-
//
|
|
63
|
-
//
|
|
61
|
+
// Fallback for platforms/arches without a shipped prebuilt binary.
|
|
62
|
+
// Since v0.2.0 the CLI depends on the `flutter_ota_kit` Flutter package, so
|
|
63
|
+
// dependency resolution needs `flutter pub get` (not `dart pub get`). The CLI
|
|
64
|
+
// entrypoint itself only touches pure-Dart backend code, so `dart run` of the
|
|
65
|
+
// resolved package still works.
|
|
64
66
|
const configPath = path.join(cliDir, '.dart_tool', 'package_config.json');
|
|
65
67
|
if (!fs.existsSync(configPath)) {
|
|
66
|
-
const getRes = spawnSync('
|
|
68
|
+
const getRes = spawnSync('flutter', ['pub', 'get'], { stdio: 'inherit', cwd: cliDir });
|
|
67
69
|
if (getRes.status !== 0) {
|
|
68
70
|
console.error(
|
|
69
|
-
'flutter-ota: `
|
|
70
|
-
`a prebuilt manually:\n cd ${cliDir} &&
|
|
71
|
-
`bin/flutter_ota_kit.dart -o ${binPath}`,
|
|
71
|
+
'flutter-ota: `flutter pub get` failed. Install the Flutter SDK or ' +
|
|
72
|
+
`build a prebuilt manually:\n cd ${cliDir} && flutter pub get && ` +
|
|
73
|
+
`dart compile exe bin/flutter_ota_kit.dart -o ${binPath}`,
|
|
72
74
|
);
|
|
73
75
|
process.exit(1);
|
|
74
76
|
}
|
|
75
77
|
}
|
|
76
|
-
chmodIfNeeded(binPath);
|
|
77
78
|
run('dart', [sourceEntry, ...process.argv.slice(2)]);
|
|
78
79
|
} else {
|
|
79
80
|
console.error(
|
|
80
81
|
`flutter-ota: no prebuilt binary for ${platformName}-${archName} and ` +
|
|
81
|
-
'the
|
|
82
|
-
'platform/arch with a shipped prebuilt binary.',
|
|
82
|
+
'the Flutter SDK was not found. Install Flutter (https://flutter.dev) or ' +
|
|
83
|
+
'use a platform/arch with a shipped prebuilt binary.',
|
|
83
84
|
);
|
|
84
85
|
process.exit(1);
|
|
85
86
|
}
|
|
@@ -1,5 +1,149 @@
|
|
|
1
1
|
# flutter_ota_kit_cli
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@_nazmiforreal/flutter-ota)
|
|
4
|
+
[](../../LICENSE)
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
### The command line for [flutter_ota_kit](https://pub.dev/packages/flutter_ota_kit) — build patches, deploy them to your backend, and manage rollouts.
|
|
7
|
+
|
|
8
|
+
`flutter-ota` is the companion CLI for **flutter_ota_kit**, open-source OTA code
|
|
9
|
+
push for Flutter Android. It packs a release APK into a signed patch, uploads it
|
|
10
|
+
to the backend **you** own (Supabase / Postgres / Cloudflare / AWS / PocketBase),
|
|
11
|
+
and gives you first-class commands for channels, staged rollouts, and instant
|
|
12
|
+
rollback.
|
|
13
|
+
|
|
14
|
+
> This tool ships via npm as `@_nazmiforreal/flutter-ota`. The runtime SDK your
|
|
15
|
+
> app depends on is the separate [`flutter_ota_kit`](https://pub.dev/packages/flutter_ota_kit)
|
|
16
|
+
> pub package.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Install
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm i -g @_nazmiforreal/flutter-ota
|
|
24
|
+
flutter-ota --help
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
A prebuilt `linux-x64` binary ships in the package. On other platforms the CLI
|
|
28
|
+
compiles from bundled Dart source on first install, which needs the
|
|
29
|
+
[**Flutter SDK**](https://flutter.dev) (the CLI shares the `flutter_ota_kit`
|
|
30
|
+
package). No Flutter? Point `flutter-ota` at a prebuilt binary you build once
|
|
31
|
+
with `dart compile exe`.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## The 60-second workflow
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
# 1. Scaffold config + a setup helper for your backend (adds the latest
|
|
39
|
+
# flutter_ota_kit to your pubspec automatically)
|
|
40
|
+
flutter-ota init supabase # or: postgres | cloudflare | aws | pocketbase
|
|
41
|
+
|
|
42
|
+
# 2. Provision the backend (Supabase & PocketBase are fully automated)
|
|
43
|
+
flutter-ota migrate supabase
|
|
44
|
+
|
|
45
|
+
# 3. Build the release APK, then pack it into a device-ready patch
|
|
46
|
+
flutter build apk --release
|
|
47
|
+
flutter-ota build \
|
|
48
|
+
--apk build/app/outputs/flutter-apk/app-release.apk \
|
|
49
|
+
--version 1.0.1 \
|
|
50
|
+
--target-version-code 100
|
|
51
|
+
|
|
52
|
+
# 4. Sign + deploy it to a channel
|
|
53
|
+
flutter-ota deploy --source dist --channel production \
|
|
54
|
+
--target-app-version 1.0.0 --force -m "hotfix: crash on login"
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Devices pick up the patch on their next launch. To pull it back:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
flutter-ota rollback --channel production
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Commands
|
|
66
|
+
|
|
67
|
+
| Command | What it does |
|
|
68
|
+
|---------|--------------|
|
|
69
|
+
| `init <backend>` | Scaffold `.flutter_ota_kit/config.json`, `.env`, and `lib/flutter_ota_kit_setup.dart`; add the SDK dependency + `INTERNET` permission |
|
|
70
|
+
| `build` | Pack a release APK into a device-ready `dist/patch.zip` (all ABIs by default) |
|
|
71
|
+
| `deploy` | Upload + register a bundle; sign it with `--key` |
|
|
72
|
+
| `bundle` | `list` / `show` / `delete` / `disable` / `enable` / `force` / `promote` / `update` |
|
|
73
|
+
| `channel` | `list` / `get` / `set` the live bundle per channel |
|
|
74
|
+
| `rollback` | Disable the latest enabled bundle on a channel (or roll back to a specific one) |
|
|
75
|
+
| `storage` | `list` / `delete` stored bundle objects |
|
|
76
|
+
| `migrate` | Provision the backend schema (Supabase / Postgres / Cloudflare / AWS / PocketBase) |
|
|
77
|
+
| `keys` | Generate an Ed25519 signing keypair |
|
|
78
|
+
| `fingerprint` | Compute a deterministic build fingerprint for fingerprint-targeted rollouts |
|
|
79
|
+
| `doctor` | Diagnose the environment + backend connectivity |
|
|
80
|
+
| `config` | `get` / `set` / `list` config values |
|
|
81
|
+
| `console` | Open the web console |
|
|
82
|
+
| `pocketbase` | Manage a local single-binary PocketBase backend (install / serve / …) |
|
|
83
|
+
|
|
84
|
+
Every command has help, including nested subcommands:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
flutter-ota deploy --help
|
|
88
|
+
flutter-ota bundle list --help
|
|
89
|
+
flutter-ota pocketbase records list --help
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Meaningful short flags map to the option's own name — e.g. on `deploy`:
|
|
93
|
+
`-s`ource, `-c`hannel, `-m`essage, `-f`orce, `-t`arget-app-version,
|
|
94
|
+
`-k`ey, `-b`ackend.
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Backends
|
|
99
|
+
|
|
100
|
+
Select one with `--backend supabase|postgres|cloudflare|aws|pocketbase` (or set
|
|
101
|
+
`provider` in `.flutter_ota_kit/config.json`). Each resolves settings with a
|
|
102
|
+
clear precedence:
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
explicit flag > environment variable > .flutter_ota_kit/config.json > default
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Config file search order: `./.flutter_ota_kit/config.json`, then the global
|
|
109
|
+
`~/.flutter_ota_kit/config.json`. Secrets (service-role keys, DB passwords,
|
|
110
|
+
tokens) belong in your shell environment or `.env` — never in committed config.
|
|
111
|
+
|
|
112
|
+
| Backend | Provisioning |
|
|
113
|
+
|---------|--------------|
|
|
114
|
+
| **Supabase** | `migrate supabase` runs SQL + creates the storage bucket — fully automated |
|
|
115
|
+
| **PocketBase** | `pocketbase install` + `pocketbase serve` — single binary, schema auto-installed |
|
|
116
|
+
| **Postgres** | `migrate postgres` applies the SQL migrations |
|
|
117
|
+
| **Cloudflare** | `migrate cloudflare` creates D1 + R2 and runs SQL |
|
|
118
|
+
| **AWS** | No SQL — the S3 bucket/prefix is created on first `deploy` |
|
|
119
|
+
|
|
120
|
+
See the [Backends guide](https://github.com/HYPER12755/flutter-ota-kit/blob/main/doc/backends.md)
|
|
121
|
+
for per-backend env vars and setup.
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## Signing
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
flutter-ota keys --save # generate a keypair, save the public half
|
|
129
|
+
flutter-ota deploy --key <private-file> # sign the bundle (Ed25519 over the MD5)
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Put the public key in your app via `FlutterPatcher.init(publicKeyBase64: '…')`;
|
|
133
|
+
keep the private key on your CI/build machine, never in the app bundle.
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Documentation
|
|
138
|
+
|
|
139
|
+
- [CLI Reference](https://github.com/HYPER12755/flutter-ota-kit/blob/main/doc/cli-reference.md) — every command + flag
|
|
140
|
+
- [Getting Started](https://github.com/HYPER12755/flutter-ota-kit/blob/main/doc/getting-started.md)
|
|
141
|
+
- [Backends](https://github.com/HYPER12755/flutter-ota-kit/blob/main/doc/backends.md)
|
|
142
|
+
- [Configuration](https://github.com/HYPER12755/flutter-ota-kit/blob/main/doc/configuration.md)
|
|
143
|
+
- [Production Playbook](https://github.com/HYPER12755/flutter-ota-kit/blob/main/doc/production-playbook.md)
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## License
|
|
148
|
+
|
|
149
|
+
MIT
|
|
@@ -22,7 +22,7 @@ export 'src/util.dart';
|
|
|
22
22
|
|
|
23
23
|
// Re-export the PocketBase client so CLI commands can probe PB health
|
|
24
24
|
// without pulling the plugin in separately.
|
|
25
|
-
export 'package:
|
|
25
|
+
export 'package:flutter_ota_kit/src/pkg/pocketbase/flutter_ota_kit_pocketbase.dart'
|
|
26
26
|
show PocketBaseClient;
|
|
27
27
|
|
|
28
28
|
export 'src/commands/init.dart';
|
|
@@ -85,13 +85,15 @@ Future<int> run(List<String> args) async {
|
|
|
85
85
|
final msg = e.message;
|
|
86
86
|
|
|
87
87
|
// Missing subcommand → show the command's own help + suggestions.
|
|
88
|
+
// Handles nested paths too (e.g. "flutter-ota pocketbase records"), not
|
|
89
|
+
// just single-word commands.
|
|
88
90
|
if (msg.startsWith('Missing subcommand')) {
|
|
89
|
-
final match = RegExp(r'"flutter-ota (
|
|
91
|
+
final match = RegExp(r'"flutter-ota ([^"]+)"').firstMatch(msg);
|
|
90
92
|
if (match != null) {
|
|
91
|
-
final cmd = runner
|
|
93
|
+
final cmd = _resolveCommandPath(runner, match.group(1)!.split(' '));
|
|
92
94
|
if (cmd != null) {
|
|
93
95
|
_printMissingSubcommand(cmd);
|
|
94
|
-
return
|
|
96
|
+
return 64;
|
|
95
97
|
}
|
|
96
98
|
}
|
|
97
99
|
}
|
|
@@ -103,7 +105,7 @@ Future<int> run(List<String> args) async {
|
|
|
103
105
|
}
|
|
104
106
|
|
|
105
107
|
// Unknown command → fuzzy-match and suggest.
|
|
106
|
-
final unknownMatch = RegExp(r'Could not find a command named "?(\w+)"?')
|
|
108
|
+
final unknownMatch = RegExp(r'Could not find a command named "?([\w-]+)"?')
|
|
107
109
|
.firstMatch(msg);
|
|
108
110
|
if (unknownMatch != null) {
|
|
109
111
|
final typed = unknownMatch.group(1)!;
|
|
@@ -111,14 +113,15 @@ Future<int> run(List<String> args) async {
|
|
|
111
113
|
return 64;
|
|
112
114
|
}
|
|
113
115
|
|
|
114
|
-
// Unknown subcommand → suggest closest subcommand.
|
|
116
|
+
// Unknown subcommand → suggest closest subcommand. Handles nested parents
|
|
117
|
+
// (e.g. "... named "nope" for "flutter-ota pocketbase records"").
|
|
115
118
|
final subMatch = RegExp(
|
|
116
|
-
r'Could not find a subcommand named "?(\w+)"? for "?flutter-ota (
|
|
119
|
+
r'Could not find a subcommand named "?([\w-]+)"? for "?flutter-ota ([^"]+)"?',
|
|
117
120
|
).firstMatch(msg);
|
|
118
121
|
if (subMatch != null) {
|
|
119
122
|
final subTyped = subMatch.group(1)!;
|
|
120
|
-
final
|
|
121
|
-
final parentCmd = runner
|
|
123
|
+
final parentPath = subMatch.group(2)!.trim().split(' ');
|
|
124
|
+
final parentCmd = _resolveCommandPath(runner, parentPath);
|
|
122
125
|
if (parentCmd != null) {
|
|
123
126
|
_printUnknownSubcommand(parentCmd, subTyped);
|
|
124
127
|
return 64;
|
|
@@ -133,6 +136,22 @@ Future<int> run(List<String> args) async {
|
|
|
133
136
|
}
|
|
134
137
|
}
|
|
135
138
|
|
|
139
|
+
/// Walk a space-separated command path (e.g. `["pocketbase", "records"]`)
|
|
140
|
+
/// from the runner down through nested subcommands. Returns the resolved
|
|
141
|
+
/// [Command], or null if any segment is unknown.
|
|
142
|
+
Command<int>? _resolveCommandPath(
|
|
143
|
+
FlutterPatcherRunner runner,
|
|
144
|
+
List<String> path,
|
|
145
|
+
) {
|
|
146
|
+
if (path.isEmpty) return null;
|
|
147
|
+
Command<int>? cmd = runner.commands[path.first];
|
|
148
|
+
for (final segment in path.skip(1)) {
|
|
149
|
+
if (cmd == null) return null;
|
|
150
|
+
cmd = cmd.subcommands[segment];
|
|
151
|
+
}
|
|
152
|
+
return cmd;
|
|
153
|
+
}
|
|
154
|
+
|
|
136
155
|
/// Show a helpful "unknown command" message with fuzzy-match suggestions.
|
|
137
156
|
void _printUnknownCommand(FlutterPatcherRunner runner, String typed) {
|
|
138
157
|
final commands = runner.commands.keys.toList();
|
|
@@ -213,6 +232,7 @@ void _printUnknownCommand(FlutterPatcherRunner runner, String typed) {
|
|
|
213
232
|
/// Show a helpful "unknown subcommand" message with suggestions.
|
|
214
233
|
void _printUnknownSubcommand(Command<int> parent, String typed) {
|
|
215
234
|
final subNames = parent.subcommands.keys.toList();
|
|
235
|
+
final parentPath = _commandPath(parent);
|
|
216
236
|
|
|
217
237
|
// Find closest subcommands.
|
|
218
238
|
final suggestions = subNames
|
|
@@ -221,14 +241,14 @@ void _printUnknownSubcommand(Command<int> parent, String typed) {
|
|
|
221
241
|
|
|
222
242
|
stderr.writeln('');
|
|
223
243
|
stderr.writeln(
|
|
224
|
-
' ${_red('✗')} Unknown subcommand: ${_red(typed)} for ${_cyan('flutter-ota $
|
|
244
|
+
' ${_red('✗')} Unknown subcommand: ${_red(typed)} for ${_cyan('flutter-ota $parentPath')}',
|
|
225
245
|
);
|
|
226
246
|
stderr.writeln('');
|
|
227
247
|
|
|
228
248
|
if (suggestions.isNotEmpty) {
|
|
229
249
|
stderr.writeln(' ${_cyan('Did you mean?')}');
|
|
230
250
|
for (final s in suggestions.take(3)) {
|
|
231
|
-
stderr.writeln(' ${_green(s)}');
|
|
251
|
+
stderr.writeln(' ${_green('$parentPath $s')}');
|
|
232
252
|
}
|
|
233
253
|
stderr.writeln('');
|
|
234
254
|
}
|
|
@@ -239,17 +259,18 @@ void _printUnknownSubcommand(Command<int> parent, String typed) {
|
|
|
239
259
|
/// Show a helpful "missing subcommand" message with all subcommand suggestions.
|
|
240
260
|
void _printMissingSubcommand(Command<int> parent) {
|
|
241
261
|
final subNames = parent.subcommands.keys.toList()..sort();
|
|
262
|
+
final parentPath = _commandPath(parent);
|
|
242
263
|
|
|
243
264
|
stderr.writeln('');
|
|
244
265
|
stderr.writeln(
|
|
245
|
-
' ${_red('✗')} Missing subcommand for ${_cyan('flutter-ota $
|
|
266
|
+
' ${_red('✗')} Missing subcommand for ${_cyan('flutter-ota $parentPath')}',
|
|
246
267
|
);
|
|
247
268
|
stderr.writeln('');
|
|
248
269
|
|
|
249
270
|
if (subNames.isNotEmpty) {
|
|
250
271
|
stderr.writeln(' ${_cyan('Available subcommands:')}');
|
|
251
272
|
for (final s in subNames) {
|
|
252
|
-
stderr.writeln(' ${_green('$
|
|
273
|
+
stderr.writeln(' ${_green('$parentPath $s')}');
|
|
253
274
|
}
|
|
254
275
|
stderr.writeln('');
|
|
255
276
|
}
|
|
@@ -257,6 +278,18 @@ void _printMissingSubcommand(Command<int> parent) {
|
|
|
257
278
|
parent.printUsage();
|
|
258
279
|
}
|
|
259
280
|
|
|
281
|
+
/// Full space-separated path of a command (e.g. `pocketbase records`),
|
|
282
|
+
/// walking up the `parent` chain. The runner itself has no name in the chain.
|
|
283
|
+
String _commandPath(Command<int> command) {
|
|
284
|
+
final parts = <String>[command.name];
|
|
285
|
+
var p = command.parent;
|
|
286
|
+
while (p != null) {
|
|
287
|
+
parts.insert(0, p.name);
|
|
288
|
+
p = p.parent;
|
|
289
|
+
}
|
|
290
|
+
return parts.join(' ');
|
|
291
|
+
}
|
|
292
|
+
|
|
260
293
|
// ── Minimal Levenshtein distance ──────────────────────────────────────────────
|
|
261
294
|
|
|
262
295
|
int _levenshtein(String a, String b) {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import 'package:
|
|
2
|
-
import 'package:
|
|
3
|
-
import 'package:
|
|
4
|
-
import 'package:
|
|
5
|
-
import 'package:
|
|
6
|
-
import 'package:
|
|
1
|
+
import 'package:flutter_ota_kit/src/pkg/aws/flutter_ota_kit_aws.dart';
|
|
2
|
+
import 'package:flutter_ota_kit/src/pkg/cloudflare/flutter_ota_kit_cloudflare.dart';
|
|
3
|
+
import 'package:flutter_ota_kit/src/pkg/plugin_core/flutter_ota_kit_plugin_core.dart';
|
|
4
|
+
import 'package:flutter_ota_kit/src/pkg/pocketbase/flutter_ota_kit_pocketbase.dart';
|
|
5
|
+
import 'package:flutter_ota_kit/src/pkg/postgres/flutter_ota_kit_postgres.dart';
|
|
6
|
+
import 'package:flutter_ota_kit/src/pkg/supabase/flutter_ota_kit_supabase.dart';
|
|
7
7
|
|
|
8
8
|
import 'config.dart';
|
|
9
9
|
|
|
@@ -17,10 +17,12 @@ class BuildCommand extends FlutterPatcherCommand {
|
|
|
17
17
|
)
|
|
18
18
|
..addMultiOption(
|
|
19
19
|
'assets',
|
|
20
|
+
abbr: 'A',
|
|
20
21
|
help: 'Asset keys to include as overlay updates (repeatable).',
|
|
21
22
|
)
|
|
22
23
|
..addOption(
|
|
23
24
|
'version',
|
|
25
|
+
abbr: 'V',
|
|
24
26
|
help: 'Patch version string (stored in manifest.version).',
|
|
25
27
|
)
|
|
26
28
|
..addOption(
|
|
@@ -151,7 +151,7 @@ class BundleShowCommand extends FlutterPatcherCommand {
|
|
|
151
151
|
? 'Backend provider [detected: $detected].'
|
|
152
152
|
: 'Backend provider.',
|
|
153
153
|
);
|
|
154
|
-
argParser.addOption('id', help: 'Bundle id.');
|
|
154
|
+
argParser.addOption('id', abbr: 'i', help: 'Bundle id.');
|
|
155
155
|
}
|
|
156
156
|
|
|
157
157
|
final FlutterPatcherConfig? config;
|
|
@@ -201,7 +201,7 @@ class BundleDeleteCommand extends FlutterPatcherCommand {
|
|
|
201
201
|
? 'Backend provider [detected: $detected].'
|
|
202
202
|
: 'Backend provider.',
|
|
203
203
|
);
|
|
204
|
-
argParser.addOption('id', help: 'Bundle id.');
|
|
204
|
+
argParser.addOption('id', abbr: 'i', help: 'Bundle id.');
|
|
205
205
|
argParser.addFlag(
|
|
206
206
|
'keep-storage',
|
|
207
207
|
help: 'Do not delete the storage object.',
|
|
@@ -252,7 +252,7 @@ class BundleDisableCommand extends FlutterPatcherCommand {
|
|
|
252
252
|
? 'Backend provider [detected: $detected].'
|
|
253
253
|
: 'Backend provider.',
|
|
254
254
|
);
|
|
255
|
-
argParser.addOption('id', help: 'Bundle id.');
|
|
255
|
+
argParser.addOption('id', abbr: 'i', help: 'Bundle id.');
|
|
256
256
|
}
|
|
257
257
|
|
|
258
258
|
final FlutterPatcherConfig? config;
|
|
@@ -290,7 +290,7 @@ class BundleEnableCommand extends FlutterPatcherCommand {
|
|
|
290
290
|
? 'Backend provider [detected: $detected].'
|
|
291
291
|
: 'Backend provider.',
|
|
292
292
|
);
|
|
293
|
-
argParser.addOption('id', help: 'Bundle id.');
|
|
293
|
+
argParser.addOption('id', abbr: 'i', help: 'Bundle id.');
|
|
294
294
|
}
|
|
295
295
|
|
|
296
296
|
final FlutterPatcherConfig? config;
|
|
@@ -328,7 +328,7 @@ class BundleForceCommand extends FlutterPatcherCommand {
|
|
|
328
328
|
? 'Backend provider [detected: $detected].'
|
|
329
329
|
: 'Backend provider.',
|
|
330
330
|
);
|
|
331
|
-
argParser.addOption('id', help: 'Bundle id.');
|
|
331
|
+
argParser.addOption('id', abbr: 'i', help: 'Bundle id.');
|
|
332
332
|
argParser.addFlag(
|
|
333
333
|
'off',
|
|
334
334
|
help: 'Clear the force-update flag instead of setting it.',
|
|
@@ -377,7 +377,7 @@ class BundlePromoteCommand extends FlutterPatcherCommand {
|
|
|
377
377
|
? 'Backend provider [detected: $detected].'
|
|
378
378
|
: 'Backend provider.',
|
|
379
379
|
);
|
|
380
|
-
argParser.addOption('id', help: 'Bundle id.');
|
|
380
|
+
argParser.addOption('id', abbr: 'i', help: 'Bundle id.');
|
|
381
381
|
argParser.addOption('channel', abbr: 'c', help: 'Target channel.');
|
|
382
382
|
}
|
|
383
383
|
|
|
@@ -426,7 +426,7 @@ class BundleUpdateCommand extends FlutterPatcherCommand {
|
|
|
426
426
|
? 'Backend provider [detected: $detected].'
|
|
427
427
|
: 'Backend provider.',
|
|
428
428
|
);
|
|
429
|
-
argParser.addOption('id', help: 'Bundle id.');
|
|
429
|
+
argParser.addOption('id', abbr: 'i', help: 'Bundle id.');
|
|
430
430
|
argParser.addOption('message', abbr: 'm', help: 'New release message.');
|
|
431
431
|
argParser.addOption(
|
|
432
432
|
'target-version',
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import 'dart:io';
|
|
2
2
|
|
|
3
|
-
import 'package:
|
|
3
|
+
import 'package:flutter_ota_kit/src/pkg/core/flutter_ota_kit_core.dart';
|
|
4
4
|
|
|
5
5
|
import '../backend.dart';
|
|
6
6
|
import '../cli_base.dart';
|
|
@@ -37,10 +37,12 @@ class DeployCommand extends FlutterPatcherCommand {
|
|
|
37
37
|
argParser.addFlag('force', abbr: 'f', help: 'Force the update on clients.');
|
|
38
38
|
argParser.addOption(
|
|
39
39
|
'target-app-version',
|
|
40
|
+
abbr: 't',
|
|
40
41
|
help: 'Semver range target (XOR with fingerprint-hash).',
|
|
41
42
|
);
|
|
42
43
|
argParser.addOption(
|
|
43
44
|
'fingerprint-hash',
|
|
45
|
+
abbr: 'F',
|
|
44
46
|
help: 'Fingerprint hash target (XOR with target-app-version).',
|
|
45
47
|
);
|
|
46
48
|
argParser.addOption(
|
|
@@ -50,6 +52,7 @@ class DeployCommand extends FlutterPatcherCommand {
|
|
|
50
52
|
);
|
|
51
53
|
argParser.addOption(
|
|
52
54
|
'git-commit-hash',
|
|
55
|
+
abbr: 'g',
|
|
53
56
|
help: 'Git commit hash (auto-detected).',
|
|
54
57
|
);
|
|
55
58
|
argParser.addOption(
|