@_nazmiforreal/flutter-ota 0.1.25 → 0.1.27

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.
Files changed (256) hide show
  1. package/bin/flutter-ota-linux-x64 +0 -0
  2. package/bin/flutter-ota.js +12 -11
  3. package/dart-src/packages/cli-tools/lib/flutter_ota_kit_cli.dart +46 -13
  4. package/dart-src/packages/cli-tools/lib/src/backend.dart +6 -6
  5. package/dart-src/packages/cli-tools/lib/src/commands/build.dart +2 -0
  6. package/dart-src/packages/cli-tools/lib/src/commands/bundle.dart +7 -7
  7. package/dart-src/packages/cli-tools/lib/src/commands/deploy.dart +4 -1
  8. package/dart-src/packages/cli-tools/lib/src/commands/pocketbase.dart +1 -1
  9. package/dart-src/packages/cli-tools/lib/src/commands/rollback.dart +1 -1
  10. package/dart-src/packages/cli-tools/lib/src/config.dart +5 -5
  11. package/dart-src/packages/cli-tools/lib/src/operations.dart +2 -2
  12. package/dart-src/packages/cli-tools/pubspec.yaml +8 -21
  13. package/dart-src/packages/cli-tools/test/backends_test.dart +3 -3
  14. package/dart-src/packages/cli-tools/test/cli_test.dart +1 -1
  15. package/dart-src/packages/cli-tools/test/mocks/mock_aws_s3_client.dart +2 -2
  16. package/dart-src/packages/cli-tools/test/mocks/mock_d1_client.dart +2 -2
  17. package/dart-src/packages/cli-tools/test/mocks/mock_pocketbase_client.dart +4 -1
  18. package/dart-src/packages/cli-tools/test/mocks/mock_postgres_client.dart +2 -2
  19. package/dart-src/packages/cli-tools/test/pocketbase_smoke_test.dart +1 -1
  20. package/dart-src/root/README.md +394 -0
  21. package/dart-src/root/analysis_options.yaml +21 -0
  22. package/dart-src/root/android/build.gradle +116 -0
  23. package/dart-src/root/android/consumer-rules.pro +23 -0
  24. package/dart-src/root/android/settings.gradle +1 -0
  25. package/dart-src/root/android/src/main/AndroidManifest.xml +21 -0
  26. package/dart-src/root/android/src/main/kotlin/com/flutter_patcher/flutter_patcher/ApplyResult.kt +52 -0
  27. package/dart-src/root/android/src/main/kotlin/com/flutter_patcher/flutter_patcher/BlacklistStore.kt +154 -0
  28. package/dart-src/root/android/src/main/kotlin/com/flutter_patcher/flutter_patcher/BootDiagnosticStore.kt +150 -0
  29. package/dart-src/root/android/src/main/kotlin/com/flutter_patcher/flutter_patcher/CrashGuard.kt +271 -0
  30. package/dart-src/root/android/src/main/kotlin/com/flutter_patcher/flutter_patcher/FlutterPatcherApplication.kt +201 -0
  31. package/dart-src/root/android/src/main/kotlin/com/flutter_patcher/flutter_patcher/FlutterPatcherAutoInitProvider.kt +93 -0
  32. package/dart-src/root/android/src/main/kotlin/com/flutter_patcher/flutter_patcher/FlutterPatcherPlugin.kt +245 -0
  33. package/dart-src/root/android/src/main/kotlin/com/flutter_patcher/flutter_patcher/LoaderHook.kt +298 -0
  34. package/dart-src/root/android/src/main/kotlin/com/flutter_patcher/flutter_patcher/PatchManager.kt +1579 -0
  35. package/dart-src/root/android/src/main/kotlin/com/flutter_patcher/flutter_patcher/PatcherConfig.kt +173 -0
  36. package/dart-src/root/android/src/main/kotlin/com/flutter_patcher/flutter_patcher/SignatureVerifier.kt +177 -0
  37. package/dart-src/root/android/src/test/kotlin/com/flutter_patcher/flutter_patcher/CrashGuardTest.kt +61 -0
  38. package/dart-src/root/android/src/test/kotlin/com/flutter_patcher/flutter_patcher/LoaderHookTest.kt +25 -0
  39. package/dart-src/root/android/src/test/kotlin/com/flutter_patcher/flutter_patcher/PatchManagerTest.kt +401 -0
  40. package/dart-src/root/android/src/test/kotlin/com/flutter_patcher/flutter_patcher/PatcherConfigTest.kt +30 -0
  41. package/dart-src/root/bin/pack.dart +182 -0
  42. package/dart-src/root/lib/flutter_ota_kit.dart +1170 -0
  43. package/dart-src/root/lib/src/app_version_resolver.dart +36 -0
  44. package/dart-src/root/lib/src/aws_update_source.dart +97 -0
  45. package/dart-src/root/lib/src/blacklist.dart +54 -0
  46. package/dart-src/root/lib/src/boot_diagnostic.dart +138 -0
  47. package/dart-src/root/lib/src/cloudflare_update_source.dart +97 -0
  48. package/dart-src/root/lib/src/flutter_ota_app.dart +69 -0
  49. package/dart-src/root/lib/src/io.dart +48 -0
  50. package/dart-src/root/lib/src/io_stub.dart +19 -0
  51. package/dart-src/root/lib/src/ota_progress_overlay.dart +987 -0
  52. package/dart-src/root/lib/src/pack/pack.dart +434 -0
  53. package/dart-src/root/lib/src/patch_info.dart +12 -0
  54. package/dart-src/root/lib/src/patcher_channel.dart +160 -0
  55. package/dart-src/{plugins/aws/lib → root/lib/src/pkg/aws}/src/aws_database.dart +1 -1
  56. package/dart-src/{plugins/aws/lib → root/lib/src/pkg/aws}/src/aws_s3_client.dart +1 -1
  57. package/dart-src/{plugins/aws/lib → root/lib/src/pkg/aws}/src/aws_storage.dart +1 -1
  58. package/dart-src/{plugins/aws/lib → root/lib/src/pkg/aws}/src/aws_storage_profile.dart +1 -1
  59. package/dart-src/{plugins/aws/lib → root/lib/src/pkg/aws}/src/with_cloudfront_signed_url.dart +1 -1
  60. package/dart-src/root/lib/src/pkg/client/flutter_ota_kit_client.dart +1 -0
  61. package/dart-src/root/lib/src/pkg/client/src/server_update_source.dart +46 -0
  62. package/dart-src/{plugins/cloudflare/lib → root/lib/src/pkg/cloudflare}/src/cloudflare_worker_database.dart +1 -1
  63. package/dart-src/{plugins/cloudflare/lib → root/lib/src/pkg/cloudflare}/src/d1_build_where.dart +1 -1
  64. package/dart-src/{plugins/cloudflare/lib → root/lib/src/pkg/cloudflare}/src/d1_bundle_mapper.dart +3 -3
  65. package/dart-src/{plugins/cloudflare/lib → root/lib/src/pkg/cloudflare}/src/d1_database.dart +1 -1
  66. package/dart-src/{plugins/cloudflare/lib → root/lib/src/pkg/cloudflare}/src/d1_database_plugin.dart +2 -2
  67. package/dart-src/{plugins/cloudflare/lib → root/lib/src/pkg/cloudflare}/src/r2_s3_client.dart +1 -1
  68. package/dart-src/{plugins/cloudflare/lib → root/lib/src/pkg/cloudflare}/src/r2_storage.dart +1 -1
  69. package/dart-src/{plugins/cloudflare/lib → root/lib/src/pkg/cloudflare}/src/r2_storage_profile.dart +1 -1
  70. package/dart-src/{packages/core/lib → root/lib/src/pkg/core}/src/status.dart +1 -1
  71. package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/flutter_ota_kit_plugin_core.dart +1 -1
  72. package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/create_blob_database_plugin.dart +1 -1
  73. package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/filter_compatible_app_versions.dart +1 -1
  74. package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/get_update_info.dart +1 -1
  75. package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/request_update_bundle_state.dart +1 -1
  76. package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/resolve_update_info_from_bundles.dart +1 -1
  77. package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/types.dart +2 -2
  78. package/dart-src/{plugins/pocketbase/lib → root/lib/src/pkg/pocketbase}/src/pocketbase_bundle_mapper.dart +2 -2
  79. package/dart-src/{plugins/pocketbase/lib → root/lib/src/pkg/pocketbase}/src/pocketbase_database.dart +26 -15
  80. package/dart-src/{plugins/pocketbase/lib → root/lib/src/pkg/pocketbase}/src/pocketbase_storage.dart +1 -1
  81. package/dart-src/{plugins/postgres/lib → root/lib/src/pkg/postgres}/src/postgres_bundle_mapper.dart +2 -2
  82. package/dart-src/{plugins/postgres/lib → root/lib/src/pkg/postgres}/src/postgres_database.dart +2 -2
  83. package/dart-src/{plugins/postgres/lib → root/lib/src/pkg/postgres}/src/postgres_get_update_info.dart +2 -2
  84. package/dart-src/{plugins/postgres/lib → root/lib/src/pkg/postgres}/src/postgres_storage.dart +1 -1
  85. package/dart-src/{plugins/postgres/lib → root/lib/src/pkg/postgres}/src/postgres_types.dart +1 -1
  86. package/dart-src/{plugins/supabase/lib → root/lib/src/pkg/supabase}/src/supabase_bundle_mapper.dart +2 -2
  87. package/dart-src/{plugins/supabase/lib → root/lib/src/pkg/supabase}/src/supabase_database.dart +2 -2
  88. package/dart-src/{plugins/supabase/lib → root/lib/src/pkg/supabase}/src/supabase_edge_function_database.dart +1 -1
  89. package/dart-src/{plugins/supabase/lib → root/lib/src/pkg/supabase}/src/supabase_edge_function_storage.dart +1 -1
  90. package/dart-src/{plugins/supabase/lib → root/lib/src/pkg/supabase}/src/supabase_storage.dart +1 -1
  91. package/dart-src/root/lib/src/pocketbase_update_source.dart +107 -0
  92. package/dart-src/root/lib/src/postgres_update_source.dart +95 -0
  93. package/dart-src/root/lib/src/shared_update_check.dart +131 -0
  94. package/dart-src/root/lib/src/supabase_update_source.dart +93 -0
  95. package/dart-src/root/pubspec.yaml +54 -0
  96. package/package.json +2 -1
  97. package/scripts/postinstall.js +17 -13
  98. package/scripts/vendor.sh +22 -7
  99. package/dart-src/packages/core/CHANGELOG.md +0 -21
  100. package/dart-src/packages/core/README.md +0 -23
  101. package/dart-src/packages/core/example/lib/main.dart +0 -69
  102. package/dart-src/packages/core/pubspec.yaml +0 -13
  103. package/dart-src/packages/core/test/rollout_test.dart +0 -135
  104. package/dart-src/packages/core/test/semver_test.dart +0 -55
  105. package/dart-src/packages/core/test/semver_vectors.json +0 -1
  106. package/dart-src/packages/core/test/types_test.dart +0 -131
  107. package/dart-src/packages/core/test/uuid_test.dart +0 -40
  108. package/dart-src/packages/core/tool/dbg.dart +0 -7
  109. package/dart-src/plugins/aws/.gitkeep +0 -0
  110. package/dart-src/plugins/aws/CHANGELOG.md +0 -23
  111. package/dart-src/plugins/aws/LICENSE +0 -21
  112. package/dart-src/plugins/aws/README.md +0 -28
  113. package/dart-src/plugins/aws/example/lib/main.dart +0 -60
  114. package/dart-src/plugins/aws/pubspec.yaml +0 -30
  115. package/dart-src/plugins/aws/test/aws_database_test.dart +0 -161
  116. package/dart-src/plugins/aws/test/aws_storage_test.dart +0 -73
  117. package/dart-src/plugins/aws/test/mock_aws_s3_client.dart +0 -78
  118. package/dart-src/plugins/cloudflare/.gitkeep +0 -0
  119. package/dart-src/plugins/cloudflare/CHANGELOG.md +0 -23
  120. package/dart-src/plugins/cloudflare/LICENSE +0 -21
  121. package/dart-src/plugins/cloudflare/README.md +0 -25
  122. package/dart-src/plugins/cloudflare/example/lib/main.dart +0 -62
  123. package/dart-src/plugins/cloudflare/migrations/0001_hot-updater_init.sql +0 -16
  124. package/dart-src/plugins/cloudflare/migrations/0002_hot-updater_0.13.0.sql +0 -8
  125. package/dart-src/plugins/cloudflare/migrations/0003_hot-updater_0.18.0.sql +0 -38
  126. package/dart-src/plugins/cloudflare/migrations/0004_hot-updater_0.29.0.sql +0 -11
  127. package/dart-src/plugins/cloudflare/migrations/0005_hot-updater_0.31.0.sql +0 -24
  128. package/dart-src/plugins/cloudflare/pubspec.yaml +0 -28
  129. package/dart-src/plugins/cloudflare/sql/bundles.sql +0 -42
  130. package/dart-src/plugins/cloudflare/test/cloudflare_worker_database_test.dart +0 -126
  131. package/dart-src/plugins/cloudflare/test/d1_bundle_mapper_test.dart +0 -106
  132. package/dart-src/plugins/cloudflare/test/d1_database_test.dart +0 -200
  133. package/dart-src/plugins/cloudflare/test/mock_d1_client.dart +0 -261
  134. package/dart-src/plugins/cloudflare/test/mock_r2_client.dart +0 -78
  135. package/dart-src/plugins/cloudflare/test/r2_storage_test.dart +0 -74
  136. package/dart-src/plugins/plugin-core/CHANGELOG.md +0 -20
  137. package/dart-src/plugins/plugin-core/LICENSE +0 -21
  138. package/dart-src/plugins/plugin-core/README.md +0 -21
  139. package/dart-src/plugins/plugin-core/example/lib/main.dart +0 -61
  140. package/dart-src/plugins/plugin-core/pubspec.yaml +0 -23
  141. package/dart-src/plugins/plugin-core/test/asset_storage_layout_test.dart +0 -170
  142. package/dart-src/plugins/plugin-core/test/bundle_unit_of_work_store_test.dart +0 -74
  143. package/dart-src/plugins/plugin-core/test/bundle_unit_of_work_test.dart +0 -345
  144. package/dart-src/plugins/plugin-core/test/create_blob_database_plugin_test.dart +0 -843
  145. package/dart-src/plugins/plugin-core/test/create_database_plugin_test.dart +0 -298
  146. package/dart-src/plugins/plugin-core/test/create_storage_plugin_test.dart +0 -195
  147. package/dart-src/plugins/plugin-core/test/generate_min_bundle_id_test.dart +0 -56
  148. package/dart-src/plugins/plugin-core/test/get_update_info_test.dart +0 -1589
  149. package/dart-src/plugins/plugin-core/test/helpers_test.dart +0 -283
  150. package/dart-src/plugins/plugin-core/test/query_bundles_test.dart +0 -202
  151. package/dart-src/plugins/plugin-core/test/request_update_bundle_state_test.dart +0 -86
  152. package/dart-src/plugins/plugin-core/test/uuidv7_test.dart +0 -88
  153. package/dart-src/plugins/pocketbase/CHANGELOG.md +0 -23
  154. package/dart-src/plugins/pocketbase/LICENSE +0 -21
  155. package/dart-src/plugins/pocketbase/README.md +0 -54
  156. package/dart-src/plugins/pocketbase/example/lib/main.dart +0 -62
  157. package/dart-src/plugins/pocketbase/pubspec.yaml +0 -26
  158. package/dart-src/plugins/pocketbase/test/pb_uri_test.dart +0 -12
  159. package/dart-src/plugins/postgres/.gitkeep +0 -0
  160. package/dart-src/plugins/postgres/CHANGELOG.md +0 -23
  161. package/dart-src/plugins/postgres/LICENSE +0 -21
  162. package/dart-src/plugins/postgres/README.md +0 -29
  163. package/dart-src/plugins/postgres/example/lib/main.dart +0 -67
  164. package/dart-src/plugins/postgres/pubspec.yaml +0 -26
  165. package/dart-src/plugins/postgres/sql/bundles.sql +0 -45
  166. package/dart-src/plugins/postgres/sql/get_target_app_version_list.sql +0 -21
  167. package/dart-src/plugins/postgres/sql/get_update_info.spec.ts +0 -171
  168. package/dart-src/plugins/postgres/sql/get_update_info_by_app_version.sql +0 -126
  169. package/dart-src/plugins/postgres/sql/get_update_info_by_fingerprint_hash.sql +0 -125
  170. package/dart-src/plugins/postgres/sql/hash_user_id.sql +0 -30
  171. package/dart-src/plugins/postgres/sql/is_device_eligible.sql +0 -237
  172. package/dart-src/plugins/postgres/sql/prepareSql.ts +0 -11
  173. package/dart-src/plugins/postgres/test/mock_postgres_client.dart +0 -320
  174. package/dart-src/plugins/postgres/test/postgres_bundle_mapper_test.dart +0 -139
  175. package/dart-src/plugins/postgres/test/postgres_database_test.dart +0 -210
  176. package/dart-src/plugins/postgres/test/postgres_storage_runtime_test.dart +0 -60
  177. package/dart-src/plugins/supabase/CHANGELOG.md +0 -24
  178. package/dart-src/plugins/supabase/LICENSE +0 -21
  179. package/dart-src/plugins/supabase/README.md +0 -53
  180. package/dart-src/plugins/supabase/example/lib/main.dart +0 -63
  181. package/dart-src/plugins/supabase/pubspec.yaml +0 -27
  182. package/dart-src/plugins/supabase/supabase/edge-functions/index.ts +0 -44
  183. package/dart-src/plugins/supabase/supabase/edge-functions/runtime.docker.integration.spec.ts +0 -968
  184. package/dart-src/plugins/supabase/supabase/migrations/20250103114225_init.sql +0 -232
  185. package/dart-src/plugins/supabase/supabase/migrations/20250314000000_hot-updater_0.13.0.sql +0 -137
  186. package/dart-src/plugins/supabase/supabase/migrations/20250516000000_hot-updater_0.18.0.sql +0 -206
  187. package/dart-src/plugins/supabase/supabase/migrations/20251014000000_hot-updater_0.21.0.sql +0 -186
  188. package/dart-src/plugins/supabase/supabase/migrations/20260401000000_hot-updater_0.29.0.sql +0 -505
  189. package/dart-src/plugins/supabase/supabase/migrations/20260414000000_hot-updater_0.30.0.sql +0 -50
  190. package/dart-src/plugins/supabase/supabase/migrations/20260422000000_hot-updater_0.31.0.sql +0 -20
  191. package/dart-src/plugins/supabase/supabase/migrations/20260520014100_hot-updater_rls.sql +0 -75
  192. package/dart-src/plugins/supabase/test/mock_supabase_client.dart +0 -654
  193. package/dart-src/plugins/supabase/test/supabase_bundle_mapper_test.dart +0 -115
  194. package/dart-src/plugins/supabase/test/supabase_database_test.dart +0 -198
  195. package/dart-src/plugins/supabase/test/supabase_storage_test.dart +0 -168
  196. /package/dart-src/{packages/core → root}/LICENSE +0 -0
  197. /package/dart-src/{plugins/aws/lib → root/lib/src/pkg/aws}/flutter_ota_kit_aws.dart +0 -0
  198. /package/dart-src/{plugins/aws/lib → root/lib/src/pkg/aws}/src/aws_cloudfront_client.dart +0 -0
  199. /package/dart-src/{plugins/aws/lib → root/lib/src/pkg/aws}/src/aws_cloudfront_signer.dart +0 -0
  200. /package/dart-src/{plugins/aws/lib → root/lib/src/pkg/aws}/src/aws_config.dart +0 -0
  201. /package/dart-src/{plugins/aws/lib → root/lib/src/pkg/aws}/src/aws_ssm_client.dart +0 -0
  202. /package/dart-src/{plugins/cloudflare/lib → root/lib/src/pkg/cloudflare}/flutter_ota_kit_cloudflare.dart +0 -0
  203. /package/dart-src/{plugins/cloudflare/lib → root/lib/src/pkg/cloudflare}/src/d1_client.dart +0 -0
  204. /package/dart-src/{plugins/cloudflare/lib → root/lib/src/pkg/cloudflare}/src/d1_config.dart +0 -0
  205. /package/dart-src/{plugins/cloudflare/lib → root/lib/src/pkg/cloudflare}/src/r2_config.dart +0 -0
  206. /package/dart-src/{packages/core/lib → root/lib/src/pkg/core}/flutter_ota_kit_core.dart +0 -0
  207. /package/dart-src/{packages/core/lib → root/lib/src/pkg/core}/src/app_update_info.dart +0 -0
  208. /package/dart-src/{packages/core/lib → root/lib/src/pkg/core}/src/bundle.dart +0 -0
  209. /package/dart-src/{packages/core/lib → root/lib/src/pkg/core}/src/bundle_artifacts.dart +0 -0
  210. /package/dart-src/{packages/core/lib → root/lib/src/pkg/core}/src/bundle_patch_artifact.dart +0 -0
  211. /package/dart-src/{packages/core/lib → root/lib/src/pkg/core}/src/changed_asset.dart +0 -0
  212. /package/dart-src/{packages/core/lib → root/lib/src/pkg/core}/src/get_bundles_args.dart +0 -0
  213. /package/dart-src/{packages/core/lib → root/lib/src/pkg/core}/src/metadata.dart +0 -0
  214. /package/dart-src/{packages/core/lib → root/lib/src/pkg/core}/src/patch_info.dart +0 -0
  215. /package/dart-src/{packages/core/lib → root/lib/src/pkg/core}/src/platform.dart +0 -0
  216. /package/dart-src/{packages/core/lib → root/lib/src/pkg/core}/src/rollout.dart +0 -0
  217. /package/dart-src/{packages/core/lib → root/lib/src/pkg/core}/src/semver.dart +0 -0
  218. /package/dart-src/{packages/core/lib → root/lib/src/pkg/core}/src/semver_range.dart +0 -0
  219. /package/dart-src/{packages/core/lib → root/lib/src/pkg/core}/src/semver_version.dart +0 -0
  220. /package/dart-src/{packages/core/lib → root/lib/src/pkg/core}/src/strategy.dart +0 -0
  221. /package/dart-src/{packages/core/lib → root/lib/src/pkg/core}/src/update_bundle_params.dart +0 -0
  222. /package/dart-src/{packages/core/lib → root/lib/src/pkg/core}/src/uuid.dart +0 -0
  223. /package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/asset_storage_layout.dart +0 -0
  224. /package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/bundle_helpers.dart +0 -0
  225. /package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/bundle_storage_layout.dart +0 -0
  226. /package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/bundle_unit_of_work.dart +0 -0
  227. /package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/bundle_unit_of_work_store.dart +0 -0
  228. /package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/calculate_pagination.dart +0 -0
  229. /package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/compression_format.dart +0 -0
  230. /package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/content_addressed_assets.dart +0 -0
  231. /package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/create_database_plugin.dart +0 -0
  232. /package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/create_storage_key_builder.dart +0 -0
  233. /package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/create_storage_plugin.dart +0 -0
  234. /package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/generate_min_bundle_id.dart +0 -0
  235. /package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/is_object.dart +0 -0
  236. /package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/legacy_asset_storage_layout.dart +0 -0
  237. /package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/paginate_bundles.dart +0 -0
  238. /package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/parse_storage_uri.dart +0 -0
  239. /package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/query_bundles.dart +0 -0
  240. /package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/storage_helpers.dart +0 -0
  241. /package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/storage_profile.dart +0 -0
  242. /package/dart-src/{plugins/plugin-core/lib → root/lib/src/pkg/plugin_core}/src/uuidv7.dart +0 -0
  243. /package/dart-src/{plugins/pocketbase/lib → root/lib/src/pkg/pocketbase}/flutter_ota_kit_pocketbase.dart +0 -0
  244. /package/dart-src/{plugins/pocketbase/lib → root/lib/src/pkg/pocketbase}/src/pocketbase_client.dart +0 -0
  245. /package/dart-src/{plugins/pocketbase/lib → root/lib/src/pkg/pocketbase}/src/pocketbase_config.dart +0 -0
  246. /package/dart-src/{plugins/postgres/lib → root/lib/src/pkg/postgres}/flutter_ota_kit_postgres.dart +0 -0
  247. /package/dart-src/{plugins/postgres/lib → root/lib/src/pkg/postgres}/src/postgres_client.dart +0 -0
  248. /package/dart-src/{plugins/postgres/lib → root/lib/src/pkg/postgres}/src/postgres_config.dart +0 -0
  249. /package/dart-src/{plugins/supabase/lib → root/lib/src/pkg/supabase}/edge.dart +0 -0
  250. /package/dart-src/{plugins/supabase/lib → root/lib/src/pkg/supabase}/flutter_ota_kit_supabase.dart +0 -0
  251. /package/dart-src/{plugins/supabase/lib → root/lib/src/pkg/supabase}/src/error_message.dart +0 -0
  252. /package/dart-src/{plugins/supabase/lib → root/lib/src/pkg/supabase}/src/supabase_client_adapter.dart +0 -0
  253. /package/dart-src/{plugins/supabase/lib → root/lib/src/pkg/supabase}/src/supabase_client_http.dart +0 -0
  254. /package/dart-src/{plugins/supabase/lib → root/lib/src/pkg/supabase}/src/supabase_config.dart +0 -0
  255. /package/dart-src/{plugins/supabase/lib → root/lib/src/pkg/supabase}/src/supabase_signed_url_batcher.dart +0 -0
  256. /package/dart-src/{plugins/supabase/lib → root/lib/src/pkg/supabase}/src/types.dart +0 -0
@@ -1,654 +0,0 @@
1
- /// Faithful mock of the Supabase client surface, mirroring hot-updater's
2
- /// `vi.mock("@supabase/supabase-js")` test seam.
3
- ///
4
- /// The mock keeps an in-memory set of `bundles` / `bundle_patches` rows and
5
- /// implements the PostgREST query-builder + RPC contract used by the database
6
- /// plugin, plus a configurable storage bucket used by the storage plugin.
7
- library;
8
-
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
-
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
-
16
- // ---------------------------------------------------------------------------
17
- // In-memory row store
18
- // ---------------------------------------------------------------------------
19
-
20
- class Store {
21
- final Map<String, Map<String, dynamic>> bundleRows = {};
22
- final Map<String, Map<String, dynamic>> bundlePatchRows = {};
23
- }
24
-
25
- // ---------------------------------------------------------------------------
26
- // Query builder mock
27
- // ---------------------------------------------------------------------------
28
-
29
- sealed class _Filter {
30
- const _Filter();
31
- }
32
-
33
- class _EqFilter extends _Filter {
34
- final String column;
35
- final Object? value;
36
- _EqFilter(this.column, this.value);
37
- }
38
-
39
- class _CompareFilter extends _Filter {
40
- final String type; // gt | gte | lt | lte
41
- final String column;
42
- final Object? value;
43
- _CompareFilter(this.type, this.column, this.value);
44
- }
45
-
46
- class _InFilter extends _Filter {
47
- final String column;
48
- final List<Object?> values;
49
- _InFilter(this.column, this.values);
50
- }
51
-
52
- class _IsFilter extends _Filter {
53
- final String column;
54
- final Object? value;
55
- _IsFilter(this.column, this.value);
56
- }
57
-
58
- class _NotFilter extends _Filter {
59
- final String column;
60
- final String operator;
61
- final Object? value;
62
- _NotFilter(this.column, this.operator, this.value);
63
- }
64
-
65
- int _compareValues(Object? left, Object? right) {
66
- if (left is String && right is String) return left.compareTo(right);
67
- if (left is num && right is num) return left.compareTo(right);
68
- if (left is bool && right is bool) {
69
- return (left ? 1 : 0).compareTo(right ? 1 : 0);
70
- }
71
- return left.toString().compareTo(right.toString());
72
- }
73
-
74
- class _MockFilterBuilder implements SupabaseFilterBuilderLike {
75
- _MockFilterBuilder(this._store, this._table, this._mode, {this.head = false});
76
-
77
- final Store _store;
78
- final String _table;
79
- final String _mode;
80
- final bool head;
81
- final bool count = false;
82
-
83
- final List<_Filter> _filters = [];
84
- bool ascending = true;
85
- int? limitValue;
86
- int? rangeStart;
87
- int? rangeEnd;
88
- bool singleRow = false;
89
-
90
- @override
91
- SupabaseFilterBuilderLike eq(String column, Object? value) {
92
- _filters.add(_EqFilter(column, value));
93
- return this;
94
- }
95
-
96
- @override
97
- SupabaseFilterBuilderLike gt(String column, Object? value) {
98
- _filters.add(_CompareFilter('gt', column, value));
99
- return this;
100
- }
101
-
102
- @override
103
- SupabaseFilterBuilderLike gte(String column, Object? value) {
104
- _filters.add(_CompareFilter('gte', column, value));
105
- return this;
106
- }
107
-
108
- @override
109
- SupabaseFilterBuilderLike lt(String column, Object? value) {
110
- _filters.add(_CompareFilter('lt', column, value));
111
- return this;
112
- }
113
-
114
- @override
115
- SupabaseFilterBuilderLike lte(String column, Object? value) {
116
- _filters.add(_CompareFilter('lte', column, value));
117
- return this;
118
- }
119
-
120
- @override
121
- SupabaseFilterBuilderLike in_(String column, List<Object?> values) {
122
- _filters.add(_InFilter(column, values));
123
- return this;
124
- }
125
-
126
- @override
127
- SupabaseFilterBuilderLike isFilter(String column, Object? value) {
128
- _filters.add(_IsFilter(column, value));
129
- return this;
130
- }
131
-
132
- @override
133
- SupabaseFilterBuilderLike not(String column, String operator, Object? value) {
134
- _filters.add(_NotFilter(column, operator, value));
135
- return this;
136
- }
137
-
138
- @override
139
- SupabaseFilterBuilderLike order(String column, {bool? ascending}) {
140
- this.ascending = ascending ?? true;
141
- return this;
142
- }
143
-
144
- @override
145
- SupabaseFilterBuilderLike limit(int value) {
146
- limitValue = value;
147
- return this;
148
- }
149
-
150
- @override
151
- SupabaseFilterBuilderLike range(int from, int to) {
152
- rangeStart = from;
153
- rangeEnd = to;
154
- return this;
155
- }
156
-
157
- @override
158
- SupabaseFilterBuilderLike single() {
159
- singleRow = true;
160
- return this;
161
- }
162
-
163
- List<Map<String, dynamic>> _rowsForTable() => _table == 'bundles'
164
- ? _store.bundleRows.values.toList()
165
- : _store.bundlePatchRows.values.toList();
166
-
167
- List<Map<String, dynamic>> _getFilteredRows() {
168
- var rows = _rowsForTable();
169
- for (final filter in _filters) {
170
- rows = rows.where((row) {
171
- return switch (filter) {
172
- _EqFilter(:final column, :final value) => row[column] == value,
173
- _CompareFilter(:final type, :final column, :final value) =>
174
- switch (type) {
175
- 'gt' => _compareValues(row[column], value) > 0,
176
- 'gte' => _compareValues(row[column], value) >= 0,
177
- 'lt' => _compareValues(row[column], value) < 0,
178
- 'lte' => _compareValues(row[column], value) <= 0,
179
- _ => false,
180
- },
181
- _InFilter(:final column, :final values) => values.contains(
182
- row[column],
183
- ),
184
- _IsFilter(:final column, :final value) => row[column] == value,
185
- _NotFilter(:final column, :final operator, :final value) =>
186
- operator == 'is' ? row[column] != value : false,
187
- };
188
- }).toList();
189
- }
190
- return rows;
191
- }
192
-
193
- @override
194
- Future<SupabaseResponseLike> execute() async {
195
- if (_mode == 'delete') {
196
- final filtered = _getFilteredRows();
197
- for (final row in filtered) {
198
- if (_table == 'bundles') {
199
- _store.bundleRows.remove(row['id']);
200
- } else {
201
- _store.bundlePatchRows.remove(row['id']);
202
- }
203
- }
204
- return _MockResponse(data: null, error: null);
205
- }
206
-
207
- var filtered = _getFilteredRows();
208
- filtered = filtered.toList()
209
- ..sort(
210
- (a, b) =>
211
- ascending ? a['id'].compareTo(b['id']) : b['id'].compareTo(a['id']),
212
- );
213
- final total = filtered.length;
214
-
215
- if (singleRow) {
216
- final data = filtered.isEmpty ? null : filtered.first;
217
- return _MockResponse(
218
- data: data,
219
- error: data == null ? {'message': 'Row not found'} : null,
220
- );
221
- }
222
-
223
- if (head || count) {
224
- return _MockResponse(data: null, error: null, count: total);
225
- }
226
-
227
- if (rangeStart != null && rangeEnd != null) {
228
- filtered = filtered.sublist(
229
- rangeStart!,
230
- (rangeEnd! + 1).clamp(0, filtered.length),
231
- );
232
- } else if (limitValue != null && limitValue! > 0) {
233
- filtered = filtered.sublist(0, limitValue!.clamp(0, filtered.length));
234
- }
235
-
236
- return _MockResponse(data: filtered, error: null, count: total);
237
- }
238
- }
239
-
240
- // ---------------------------------------------------------------------------
241
- // Storage bucket mock
242
- // ---------------------------------------------------------------------------
243
-
244
- class _ExistsResult implements SupabaseExistsResult {
245
- _ExistsResult({this.data, this.error});
246
- @override
247
- final bool? data;
248
- @override
249
- final Object? error;
250
- @override
251
- final String? message = null;
252
- }
253
-
254
- class _SignedUrlResult implements SupabaseSignedUrlResult {
255
- _SignedUrlResult({this.signedUrl, this.error});
256
- @override
257
- final String? signedUrl;
258
- @override
259
- final Object? error;
260
- }
261
-
262
- class _SignedUrlListResult implements SupabaseSignedUrlListResult {
263
- _SignedUrlListResult({this.data, this.error});
264
- @override
265
- final List<SupabaseSignedUrlResult>? data;
266
- @override
267
- final Object? error;
268
- }
269
-
270
- class _UploadResult implements SupabaseUploadResult {
271
- _UploadResult({this.data, this.error});
272
- @override
273
- final Object? data;
274
- @override
275
- final Object? error;
276
- }
277
-
278
- class _RemoveResult implements SupabaseRemoveResult {
279
- _RemoveResult({this.data, this.error, this.message});
280
- @override
281
- final Object? data;
282
- @override
283
- final Object? error;
284
- @override
285
- final String? message;
286
- }
287
-
288
- class _DownloadResult implements SupabaseDownloadResult {
289
- _DownloadResult({this.data, this.error, this.message});
290
- @override
291
- final List<int>? data;
292
- @override
293
- final Object? error;
294
- @override
295
- final String? message;
296
- }
297
-
298
- class _ListResult implements SupabaseListResult {
299
- _ListResult({this.data, this.error});
300
- @override
301
- final List<SupabaseStorageObject>? data;
302
- @override
303
- final Object? error;
304
- }
305
-
306
- /// Configurable in-memory storage bucket.
307
- class FakeStorageBucket implements SupabaseStorageBucketLike {
308
- FakeStorageBucket({
309
- this.existsData,
310
- this.existsError,
311
- this.existsThrows,
312
- this.signedUrlData,
313
- this.signedUrlError,
314
- this.uploadData,
315
- this.uploadError,
316
- this.removeError,
317
- this.removeMessage,
318
- this.downloadData,
319
- this.downloadError,
320
- this.downloadMessage,
321
- this.listData,
322
- this.listError,
323
- this.createSignedUrlBase = 'https://example.supabase.co',
324
- });
325
-
326
- bool? existsData;
327
- Object? existsError;
328
- Object? existsThrows;
329
- String? signedUrlData;
330
- Object? signedUrlError;
331
- Object? uploadData;
332
- Object? uploadError;
333
- Object? removeError;
334
- String? removeMessage;
335
- List<int>? downloadData;
336
- Object? downloadError;
337
- String? downloadMessage;
338
- List<SupabaseStorageObject>? listData;
339
- Object? listError;
340
- final String createSignedUrlBase;
341
-
342
- final List<String> existsCalls = [];
343
- final List<String> createSignedUrlCalls = [];
344
- final List<List<String>> createSignedUrlsCalls = [];
345
- final List<String> uploadCalls = [];
346
- final List<List<String>> removeCalls = [];
347
- final List<String> downloadCalls = [];
348
- final List<String> listCalls = [];
349
-
350
- @override
351
- Future<SupabaseExistsResult> exists(String path) {
352
- existsCalls.add(path);
353
- if (existsThrows != null) {
354
- return Future.error(existsThrows!);
355
- }
356
- return Future.value(_ExistsResult(data: existsData, error: existsError));
357
- }
358
-
359
- @override
360
- Future<SupabaseSignedUrlResult> createSignedUrl(String path, int expiresIn) {
361
- createSignedUrlCalls.add(path);
362
- return Future.value(
363
- _SignedUrlResult(
364
- signedUrl: signedUrlData ?? '$createSignedUrlBase/signed-url',
365
- error: signedUrlError,
366
- ),
367
- );
368
- }
369
-
370
- @override
371
- Future<SupabaseSignedUrlListResult> createSignedUrls(
372
- List<String> paths,
373
- int expiresIn,
374
- ) {
375
- createSignedUrlsCalls.add(List.of(paths));
376
- return Future.value(
377
- _SignedUrlListResult(
378
- data: paths
379
- .map(
380
- (p) => _SignedUrlResult(
381
- signedUrl: '$createSignedUrlBase/$expiresIn/$p',
382
- error: signedUrlError,
383
- ),
384
- )
385
- .toList(),
386
- error: signedUrlError,
387
- ),
388
- );
389
- }
390
-
391
- @override
392
- Future<SupabaseUploadResult> upload(
393
- String path,
394
- List<int> fileBytes, {
395
- String? contentType,
396
- String? cacheControl,
397
- }) {
398
- uploadCalls.add(path);
399
- return Future.value(
400
- _UploadResult(data: uploadData ?? {'fullPath': path}, error: uploadError),
401
- );
402
- }
403
-
404
- @override
405
- Future<SupabaseRemoveResult> remove(List<String> paths) {
406
- removeCalls.add(List.of(paths));
407
- return Future.value(
408
- _RemoveResult(data: [], error: removeError, message: removeMessage),
409
- );
410
- }
411
-
412
- @override
413
- Future<SupabaseDownloadResult> download(String path) {
414
- downloadCalls.add(path);
415
- return Future.value(
416
- _DownloadResult(
417
- data: downloadData,
418
- error: downloadError,
419
- message: downloadMessage,
420
- ),
421
- );
422
- }
423
-
424
- @override
425
- Future<SupabaseListResult> list([String? prefix]) {
426
- listCalls.add(prefix ?? '');
427
- return Future.value(_ListResult(data: listData, error: listError));
428
- }
429
- }
430
-
431
- // ---------------------------------------------------------------------------
432
- // Top-level mock client
433
- // ---------------------------------------------------------------------------
434
-
435
- class _MockStorageClient implements SupabaseStorageClientLike {
436
- _MockStorageClient(this.bucket);
437
- final SupabaseStorageBucketLike bucket;
438
-
439
- @override
440
- SupabaseStorageBucketLike from(String bucketName) => bucket;
441
- }
442
-
443
- class _MockQueryBuilder implements SupabaseQueryBuilderLike {
444
- _MockQueryBuilder(this._store, this._table);
445
- final Store _store;
446
- final String _table;
447
-
448
- @override
449
- SupabaseFilterBuilderLike select(String columns, {bool? count, bool? head}) =>
450
- _MockFilterBuilder(_store, _table, 'select', head: head ?? false);
451
-
452
- @override
453
- SupabaseFilterBuilderLike delete() =>
454
- _MockFilterBuilder(_store, _table, 'delete');
455
-
456
- @override
457
- Future<dynamic> upsert(dynamic values, {String? onConflict}) async {
458
- final list = values is List ? values : [values];
459
- for (final value in list) {
460
- final Map<String, dynamic> map;
461
- if (value is SupabaseBundleRow) {
462
- map = value.toJson();
463
- } else if (value is SupabaseBundlePatchRow) {
464
- map = value.toJson();
465
- } else {
466
- map = Map<String, dynamic>.from(value as Map);
467
- }
468
- if (_table == 'bundles') {
469
- _store.bundleRows[map['id'] as String] = map;
470
- } else {
471
- _store.bundlePatchRows[map['id'] as String] = map;
472
- }
473
- }
474
- return _MockResponse(data: null, error: null);
475
- }
476
- }
477
-
478
- class _MockResponse implements SupabaseResponseLike {
479
- _MockResponse({this.data, this.error, this.count});
480
- @override
481
- final Object? data;
482
- @override
483
- final Object? error;
484
- @override
485
- final int? count;
486
- }
487
-
488
- class _MockRpcResponse implements SupabaseRpcResponse {
489
- _MockRpcResponse({this.data, this.error});
490
- @override
491
- final Object? data;
492
- @override
493
- final Object? error;
494
- }
495
-
496
- /// Build an in-memory mock Supabase client backed by [store] and [bucket].
497
- SupabaseClientLike createMockSupabaseClient({
498
- required Store store,
499
- required FakeStorageBucket bucket,
500
- }) {
501
- final storageClient = _MockStorageClient(bucket);
502
-
503
- Platform platformFrom(String value) =>
504
- value == 'ios' ? Platform.ios : Platform.android;
505
-
506
- Bundle rowToBundle(Map<String, dynamic> row) =>
507
- mapRowToBundle(SupabaseBundleRow.fromJson(row));
508
-
509
- return _MockClient(store, storageClient, platformFrom, rowToBundle);
510
- }
511
-
512
- class _MockClient implements SupabaseClientLike {
513
- _MockClient(
514
- this._store,
515
- this._storage,
516
- this._platformFrom,
517
- this._rowToBundle,
518
- );
519
-
520
- final Store _store;
521
- final SupabaseStorageClientLike _storage;
522
- final Platform Function(String) _platformFrom;
523
- final Bundle Function(Map<String, dynamic>) _rowToBundle;
524
-
525
- @override
526
- SupabaseQueryBuilderLike from(String table) =>
527
- _MockQueryBuilder(_store, table);
528
-
529
- @override
530
- SupabaseStorageClientLike get storage => _storage;
531
-
532
- @override
533
- Future<SupabaseRpcResponse> rpc(
534
- String functionName, {
535
- Map<String, dynamic>? params,
536
- }) async {
537
- if (functionName == 'get_channels') {
538
- final channels = _store.bundleRows.values
539
- .map((r) => r['channel'] as String)
540
- .toSet()
541
- .map((c) => {'channel': c})
542
- .toList();
543
- return _MockRpcResponse(data: channels, error: null);
544
- }
545
-
546
- if (functionName == 'get_target_app_version_list') {
547
- final platform = params!['app_platform'] as String;
548
- final minBundleId = params['min_bundle_id'] as String;
549
- final list = _store.bundleRows.values
550
- .where(
551
- (r) =>
552
- r['platform'] == platform &&
553
- (r['id'] as String).compareTo(minBundleId) >= 0 &&
554
- r['target_app_version'] != null,
555
- )
556
- .map((r) => r['target_app_version'] as String)
557
- .toSet()
558
- .map((v) => {'target_app_version': v})
559
- .toList();
560
- return _MockRpcResponse(data: list, error: null);
561
- }
562
-
563
- if (functionName == 'get_update_info_by_app_version') {
564
- final platform = params!['app_platform'] as String;
565
- final appVersion = params['app_version'] as String;
566
- final bundleId = params['bundle_id'] as String;
567
- final minBundleId = params['min_bundle_id'] as String;
568
- final channel = params['target_channel'] as String;
569
- final targetAppVersionList = List<String>.from(
570
- params['target_app_version_list'] as List? ?? [],
571
- );
572
- final cohort = params['cohort'] as String?;
573
-
574
- final bundles = _store.bundleRows.values
575
- .where(
576
- (r) =>
577
- r['enabled'] == true &&
578
- r['platform'] == platform &&
579
- r['channel'] == channel &&
580
- (r['id'] as String).compareTo(minBundleId) >= 0 &&
581
- (targetAppVersionList.contains(r['target_app_version'])),
582
- )
583
- .map(_rowToBundle)
584
- .toList();
585
-
586
- final info = await getUpdateInfo(
587
- bundles,
588
- AppVersionGetBundlesArgs(
589
- appVersion: appVersion,
590
- bundleId: bundleId,
591
- channel: channel,
592
- minBundleId: minBundleId,
593
- platform: _platformFrom(platform),
594
- cohort: cohort,
595
- ),
596
- );
597
- return _MockRpcResponse(
598
- data: info == null ? [] : [_toUpdateInfoRow(info)],
599
- error: null,
600
- );
601
- }
602
-
603
- if (functionName == 'get_update_info_by_fingerprint_hash') {
604
- final platform = params!['app_platform'] as String;
605
- final bundleId = params['bundle_id'] as String;
606
- final minBundleId = params['min_bundle_id'] as String;
607
- final channel = params['target_channel'] as String;
608
- final fingerprintHash = params['target_fingerprint_hash'] as String;
609
- final cohort = params['cohort'] as String?;
610
-
611
- final bundles = _store.bundleRows.values
612
- .where(
613
- (r) =>
614
- r['enabled'] == true &&
615
- r['platform'] == platform &&
616
- r['channel'] == channel &&
617
- (r['id'] as String).compareTo(minBundleId) >= 0 &&
618
- r['fingerprint_hash'] == fingerprintHash,
619
- )
620
- .map(_rowToBundle)
621
- .toList();
622
-
623
- final info = await getUpdateInfo(
624
- bundles,
625
- FingerprintGetBundlesArgs(
626
- fingerprintHash: fingerprintHash,
627
- bundleId: bundleId,
628
- channel: channel,
629
- minBundleId: minBundleId,
630
- platform: _platformFrom(platform),
631
- cohort: cohort,
632
- ),
633
- );
634
- return _MockRpcResponse(
635
- data: info == null ? [] : [_toUpdateInfoRow(info)],
636
- error: null,
637
- );
638
- }
639
-
640
- return _MockRpcResponse(
641
- data: null,
642
- error: 'Unsupported RPC: $functionName',
643
- );
644
- }
645
- }
646
-
647
- Map<String, dynamic> _toUpdateInfoRow(UpdateInfo info) => {
648
- 'id': info.id,
649
- 'should_force_update': info.shouldForceUpdate,
650
- 'message': info.message,
651
- 'status': info.status == UpdateStatus.rollback ? 'ROLLBACK' : 'UPDATE',
652
- 'storage_uri': info.storageUri,
653
- 'file_hash': info.fileHash,
654
- };