@_nazmiforreal/flutter-ota 0.1.8 → 0.1.10

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 (33) hide show
  1. package/bin/flutter-ota-linux-x64 +0 -0
  2. package/bin/flutter-ota.js +3 -3
  3. package/dart-src/packages/cli-tools/LICENSE +21 -0
  4. package/dart-src/packages/cli-tools/README.md +5 -0
  5. package/dart-src/packages/cli-tools/lib/src/commands/init.dart +142 -50
  6. package/dart-src/packages/cli-tools/lib/src/config.dart +7 -7
  7. package/dart-src/packages/core/CHANGELOG.md +3 -0
  8. package/dart-src/packages/core/LICENSE +21 -0
  9. package/dart-src/packages/core/README.md +23 -0
  10. package/dart-src/packages/core/pubspec.yaml +6 -1
  11. package/dart-src/plugins/aws/CHANGELOG.md +3 -0
  12. package/dart-src/plugins/aws/LICENSE +21 -0
  13. package/dart-src/plugins/aws/README.md +28 -0
  14. package/dart-src/plugins/aws/pubspec.yaml +8 -5
  15. package/dart-src/plugins/cloudflare/CHANGELOG.md +3 -0
  16. package/dart-src/plugins/cloudflare/LICENSE +21 -0
  17. package/dart-src/plugins/cloudflare/README.md +25 -0
  18. package/dart-src/plugins/cloudflare/pubspec.yaml +8 -5
  19. package/dart-src/plugins/plugin-core/CHANGELOG.md +3 -0
  20. package/dart-src/plugins/plugin-core/LICENSE +21 -0
  21. package/dart-src/plugins/plugin-core/README.md +21 -0
  22. package/dart-src/plugins/plugin-core/pubspec.yaml +7 -2
  23. package/dart-src/plugins/postgres/CHANGELOG.md +3 -0
  24. package/dart-src/plugins/postgres/LICENSE +21 -0
  25. package/dart-src/plugins/postgres/README.md +29 -0
  26. package/dart-src/plugins/postgres/pubspec.yaml +8 -5
  27. package/dart-src/plugins/supabase/CHANGELOG.md +3 -0
  28. package/dart-src/plugins/supabase/LICENSE +21 -0
  29. package/dart-src/plugins/supabase/README.md +53 -0
  30. package/dart-src/plugins/supabase/pubspec.yaml +9 -6
  31. package/dart-src/plugins/supabase/supabase/migrations/20260520014100_hot-updater_rls.sql +11 -0
  32. package/migrations/supabase/20260520014100_hot-updater_rls.sql +11 -0
  33. package/package.json +1 -1
Binary file
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  'use strict';
3
3
 
4
- // Launcher for the flutter_patcher CLI.
4
+ // Launcher for the flutter_ota_kit CLI.
5
5
  //
6
6
  // Resolves a platform+arch-specific prebuilt binary (`flutter-ota-<os>-<arch>`)
7
7
  // shipped next to this script, falling back to `dart run` of the bundled Dart
@@ -32,7 +32,7 @@ const binName = `flutter-ota-${platformName}-${archName}${ext}`;
32
32
  const binPath = path.join(binDir, binName);
33
33
 
34
34
  const sourceEntry = path.join(
35
- binDir, '..', 'dart-src', 'packages', 'cli-tools', 'bin', 'flutter_patcher.dart',
35
+ binDir, '..', 'dart-src', 'packages', 'cli-tools', 'bin', 'flutter_ota_kit.dart',
36
36
  );
37
37
  const cliDir = path.dirname(path.dirname(sourceEntry));
38
38
 
@@ -68,7 +68,7 @@ if (fs.existsSync(binPath)) {
68
68
  console.error(
69
69
  'flutter-ota: `dart pub get` failed. Install dependencies or build ' +
70
70
  `a prebuilt manually:\n cd ${cliDir} && dart compile exe ` +
71
- `bin/flutter_patcher.dart -o ${binPath}`,
71
+ `bin/flutter_ota_kit.dart -o ${binPath}`,
72
72
  );
73
73
  process.exit(1);
74
74
  }
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 xuelinger
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,5 @@
1
+ # flutter_ota_kit_cli
2
+
3
+ Part of the [flutter_ota_kit](https://github.com/HYPER12755/flutter_ota_kit) OTA (over-the-air) update toolkit for Flutter Android.
4
+
5
+ See the project README for usage, backend setup, and the architecture overview.
@@ -7,7 +7,7 @@ import '../ui/ui.dart';
7
7
 
8
8
  /// `flutter_ota_kit init <backend>` — scaffold a Flutter project for OTA updates.
9
9
  ///
10
- /// Beyond writing the `.otat/config.json` (so every other `flutter_ota_kit` command
10
+ /// Beyond writing the `.flutter_ota_kit/config.json` (so every other `flutter_ota_kit` command
11
11
  /// knows the backend), it also drops the files a host app actually needs:
12
12
  ///
13
13
  /// * adds the `flutter_ota_kit` pub dependency to `pubspec.yaml`,
@@ -16,7 +16,7 @@ import '../ui/ui.dart';
16
16
  /// * generates `lib/flutter_ota_kit_setup.dart` that wires the selected backend
17
17
  /// and enables zero-click forced updates.
18
18
  ///
19
- /// All CLI working state is stored under `.otat/`.
19
+ /// All CLI working state is stored under `.flutter_ota_kit/`.
20
20
  class InitCommand extends FlutterPatcherCommand {
21
21
  InitCommand({this.config, this.backendOverride});
22
22
 
@@ -28,7 +28,7 @@ class InitCommand extends FlutterPatcherCommand {
28
28
 
29
29
  @override
30
30
  String get description =>
31
- 'Scaffold flutter_ota_kit integration files + .otat config for the current '
31
+ 'Scaffold flutter_ota_kit integration files + .flutter_ota_kit config for the current '
32
32
  'Flutter project. Usage: flutter_ota_kit init <supabase|postgres|cloudflare|aws>';
33
33
 
34
34
  @override
@@ -40,7 +40,7 @@ class InitCommand extends FlutterPatcherCommand {
40
40
  ..addOption('channel', abbr: 'c', defaultsTo: 'production', help: 'Default channel.')
41
41
  ..addOption('platform', defaultsTo: 'android', help: 'Default platform.')
42
42
  ..addOption('source', abbr: 's', defaultsTo: './dist', help: 'Default deploy source.')
43
- ..addFlag('global', help: 'Write to the global ~/.otat config (no scaffolding).')
43
+ ..addFlag('global', help: 'Write to the global ~/.flutter_ota_kit config (no scaffolding).')
44
44
  ..addFlag('force', abbr: 'f', help: 'Overwrite an existing config.');
45
45
 
46
46
  String? _p(String label, String? current) {
@@ -209,7 +209,7 @@ class InitCommand extends FlutterPatcherCommand {
209
209
 
210
210
  if (global) {
211
211
  stdout.writeln(
212
- ' ${yellow('⚠')} Secrets are stored in plaintext under ~/.otat. '
212
+ ' ${yellow('⚠')} Secrets are stored in plaintext under ~/.flutter_ota_kit. '
213
213
  'Restrict permissions and use a secrets manager in production.',
214
214
  );
215
215
  return;
@@ -224,6 +224,9 @@ class InitCommand extends FlutterPatcherCommand {
224
224
  stdout.writeln(
225
225
  ' 2. In lib/main.dart call ${green('await setupFlutterOta();')} '
226
226
  'right after WidgetsFlutterBinding.ensureInitialized() (before runApp).');
227
+ stdout.writeln(
228
+ ' A `.env` scaffold was written — put secrets there, then build with '
229
+ '`--dart-define-from-file=.env` (environment overrides config).');
227
230
  if (provider == 'supabase') {
228
231
  stdout.writeln(
229
232
  ' 3. Provision the backend once: ${dim('flutter_ota_kit migrate supabase')}');
@@ -242,6 +245,7 @@ class InitCommand extends FlutterPatcherCommand {
242
245
  _addPubDependency();
243
246
  _addInternetPermission();
244
247
  await _writeSetupFile(cfg, provider);
248
+ _writeEnvFile(cfg, provider);
245
249
  _ensureGitignore();
246
250
  }
247
251
 
@@ -306,22 +310,110 @@ class InitCommand extends FlutterPatcherCommand {
306
310
  void _ensureGitignore() {
307
311
  final gi = File('.gitignore');
308
312
  final content = gi.existsSync() ? gi.readAsStringSync() : '';
309
- if (content.contains('.otat/')) {
310
- step('.gitignore already ignores .otat/');
313
+ if (content.contains('.flutter_ota_kit/')) {
314
+ step('.gitignore already ignores .flutter_ota_kit/');
315
+ return;
316
+ }
317
+ final next = content.isEmpty ? '.flutter_ota_kit/\n' : '$content\n.flutter_ota_kit/\n';
318
+ gi.writeAsStringSync(next);
319
+ step('Added .flutter_ota_kit/ to .gitignore');
320
+ }
321
+
322
+ /// Write a `.env` scaffold for the selected backend. Every key is present but
323
+ /// empty by default; any value supplied during `init` (interactive prompt or
324
+ /// environment hint) is filled in so the app can be built with
325
+ /// `flutter run --dart-define-from-file=.env`. Secrets always land here (env),
326
+ /// never in committed source — the same values are also persisted to
327
+ /// `.flutter_ota_kit/config.json` for the CLI.
328
+ void _writeEnvFile(FlutterPatcherConfig cfg, String provider) {
329
+ final entries = <String, String>{};
330
+ switch (provider) {
331
+ case 'postgres':
332
+ final c = cfg.postgres;
333
+ entries['POSTGRES_HOST'] = c.host ?? '';
334
+ entries['POSTGRES_PORT'] = c.port ?? '5432';
335
+ entries['POSTGRES_DB'] = c.database ?? 'postgres';
336
+ entries['POSTGRES_USER'] = c.username ?? '';
337
+ entries['POSTGRES_PASSWORD'] = c.password ?? '';
338
+ entries['POSTGRES_SERVING_BASE_URL'] = c.servingBaseUrl ?? '';
339
+ entries['CHANNEL'] = cfg.channel;
340
+ entries['APP_VERSION'] = '1.0.0';
341
+ case 'cloudflare':
342
+ final c = cfg.cloudflare;
343
+ entries['CLOUDFLARE_ACCOUNT_ID'] = c.accountId ?? '';
344
+ entries['CLOUDFLARE_D1_DATABASE_ID'] = c.d1DatabaseId ?? '';
345
+ entries['CLOUDFLARE_API_TOKEN'] = c.apiToken ?? '';
346
+ entries['R2_BUCKET'] = c.r2Bucket ?? 'bundles';
347
+ entries['R2_ACCESS_KEY_ID'] = c.r2AccessKeyId ?? '';
348
+ entries['R2_SECRET_ACCESS_KEY'] = c.r2SecretAccessKey ?? '';
349
+ entries['R2_BASE_PATH'] = c.r2BasePath ?? '';
350
+ entries['CHANNEL'] = cfg.channel;
351
+ entries['APP_VERSION'] = '1.0.0';
352
+ case 'aws':
353
+ final c = cfg.aws;
354
+ entries['AWS_BUCKET'] = c.bucket ?? '';
355
+ entries['AWS_REGION'] = c.region ?? '';
356
+ entries['AWS_ACCESS_KEY_ID'] = c.accessKeyId ?? '';
357
+ entries['AWS_SECRET_ACCESS_KEY'] = c.secretAccessKey ?? '';
358
+ entries['AWS_ENDPOINT'] = c.endpoint ?? '';
359
+ entries['AWS_BASE_PATH'] = c.basePath ?? '';
360
+ entries['AWS_SESSION_TOKEN'] = c.sessionToken ?? '';
361
+ entries['CHANNEL'] = cfg.channel;
362
+ entries['APP_VERSION'] = '1.0.0';
363
+ case 'supabase':
364
+ default:
365
+ final c = cfg.supabase;
366
+ entries['SUPABASE_URL'] = c.url ?? '';
367
+ entries['SUPABASE_ANON_KEY'] = c.anonKey ?? '';
368
+ entries['SUPABASE_BUCKET'] = c.bucket ?? 'bundles';
369
+ entries['CHANNEL'] = cfg.channel;
370
+ entries['APP_VERSION'] = '1.0.0';
371
+ entries['SDK_VERSION'] = '1.0.0';
372
+ }
373
+
374
+ final buffer = StringBuffer();
375
+ buffer.writeln('# Generated by `flutter-ota init $provider`.');
376
+ buffer.writeln('# Fill in (or override) values, then build with:');
377
+ buffer.writeln('# flutter run --dart-define-from-file=.env');
378
+ buffer.writeln('# Environment overrides the project config and any defaults.');
379
+ for (final e in entries.entries) {
380
+ buffer.writeln('${e.key}=${e.value}');
381
+ }
382
+
383
+ final file = File('.env');
384
+ if (file.existsSync() && !(argResults!['force'] as bool)) {
385
+ step('.env already exists; left untouched (use --force to overwrite)');
311
386
  return;
312
387
  }
313
- final next = content.isEmpty ? '.otat/\n' : '$content\n.otat/\n';
388
+ file.writeAsStringSync(buffer.toString());
389
+ step('Wrote .env with $provider env scaffolding');
390
+ _ensureEnvGitignored();
391
+ }
392
+
393
+ void _ensureEnvGitignored() {
394
+ final gi = File('.gitignore');
395
+ final lines =
396
+ gi.existsSync() ? gi.readAsStringSync().split('\n') : const <String>[];
397
+ if (lines.contains('.env')) {
398
+ step('.gitignore already ignores .env');
399
+ return;
400
+ }
401
+ final next = '${gi.existsSync() ? gi.readAsStringSync() : ''}\n.env\n';
314
402
  gi.writeAsStringSync(next);
315
- step('Added .otat/ to .gitignore');
403
+ step('Added .env to .gitignore');
316
404
  }
317
405
 
318
406
  String _q(String? s) => s == null ? "''" : "'${s.replaceAll("'", "\\'")}'";
319
407
 
320
408
  /// Build the body of `lib/flutter_ota_kit_setup.dart` for the selected backend.
409
+ ///
410
+ /// Non-secret values default to the project config (written during `init` under
411
+ /// `.flutter_ota_kit/`); every value can be overridden by a build-time
412
+ /// `--dart-define` / `.env` (environment wins). Secrets (keys/tokens) default
413
+ /// to empty and are ONLY read from the environment, never hard-coded here.
321
414
  String _setupBody(FlutterPatcherConfig cfg, String provider) {
322
415
  final channel = _q(cfg.channel);
323
- final strategy = 'UpdateStrategy.appVersion';
324
- final appVersion =
416
+ final appVersionExpr =
325
417
  "const String.fromEnvironment('APP_VERSION', defaultValue: '1.0.0')";
326
418
 
327
419
  late final String configure;
@@ -330,73 +422,73 @@ class InitCommand extends FlutterPatcherCommand {
330
422
  final c = cfg.postgres;
331
423
  configure = '''
332
424
  FlutterPatcher.configurePostgres(PostgresUpdateConfig(
333
- host: ${_q(c.host)},
334
- port: ${_q(c.port ?? '5432')},
335
- database: ${_q(c.database)},
336
- username: ${_q(c.username)},
337
- password: ${_q(c.password)},
338
- servingBaseUrl: ${_q(c.servingBaseUrl)},
339
- channel: $channel,
425
+ host: const String.fromEnvironment('POSTGRES_HOST', defaultValue: ${_q(c.host ?? '')}),
426
+ port: int.tryParse(const String.fromEnvironment('POSTGRES_PORT', defaultValue: ${_q(c.port ?? '5432')})) ?? 5432,
427
+ database: const String.fromEnvironment('POSTGRES_DB', defaultValue: ${_q(c.database ?? 'postgres')}),
428
+ username: const String.fromEnvironment('POSTGRES_USER', defaultValue: ${_q(c.username ?? '')}),
429
+ password: const String.fromEnvironment('POSTGRES_PASSWORD', defaultValue: ''),
430
+ servingBaseUrl: const String.fromEnvironment('POSTGRES_SERVING_BASE_URL', defaultValue: ${_q(c.servingBaseUrl ?? '')}),
431
+ channel: const String.fromEnvironment('CHANNEL', defaultValue: $channel),
340
432
  platform: Platform.android,
341
- updateStrategy: $strategy,
342
- appVersion: $appVersion,
433
+ updateStrategy: UpdateStrategy.appVersion,
434
+ appVersion: $appVersionExpr,
343
435
  ));''';
344
436
  case 'cloudflare':
345
437
  final c = cfg.cloudflare;
346
438
  configure = '''
347
439
  FlutterPatcher.configureCloudflare(CloudflareUpdateConfig(
348
- databaseId: ${_q(c.d1DatabaseId)},
349
- accountId: ${_q(c.accountId)},
350
- cloudflareApiToken: ${_q(c.apiToken)},
351
- bucketName: ${_q(c.r2Bucket ?? 'bundles')},
352
- accessKeyId: ${_q(c.r2AccessKeyId)},
353
- secretAccessKey: ${_q(c.r2SecretAccessKey)},
354
- basePath: ${_q(c.r2BasePath)},
355
- channel: $channel,
440
+ accountId: const String.fromEnvironment('CLOUDFLARE_ACCOUNT_ID', defaultValue: ${_q(c.accountId ?? '')}),
441
+ databaseId: const String.fromEnvironment('CLOUDFLARE_D1_DATABASE_ID', defaultValue: ${_q(c.d1DatabaseId ?? '')}),
442
+ cloudflareApiToken: const String.fromEnvironment('CLOUDFLARE_API_TOKEN', defaultValue: ''),
443
+ bucketName: const String.fromEnvironment('R2_BUCKET', defaultValue: ${_q(c.r2Bucket ?? 'bundles')}),
444
+ accessKeyId: const String.fromEnvironment('R2_ACCESS_KEY_ID', defaultValue: ''),
445
+ secretAccessKey: const String.fromEnvironment('R2_SECRET_ACCESS_KEY', defaultValue: ''),
446
+ basePath: const String.fromEnvironment('R2_BASE_PATH', defaultValue: ${_q(c.r2BasePath ?? '')}),
447
+ channel: const String.fromEnvironment('CHANNEL', defaultValue: $channel),
356
448
  platform: Platform.android,
357
- updateStrategy: $strategy,
358
- appVersion: $appVersion,
449
+ updateStrategy: UpdateStrategy.appVersion,
450
+ appVersion: $appVersionExpr,
359
451
  ));''';
360
452
  case 'aws':
361
453
  final c = cfg.aws;
362
454
  configure = '''
363
455
  FlutterPatcher.configureAws(AwsUpdateConfig(
364
- bucketName: ${_q(c.bucket)},
365
- region: ${_q(c.region)},
366
- accessKeyId: ${_q(c.accessKeyId)},
367
- secretAccessKey: ${_q(c.secretAccessKey)},
368
- basePath: ${_q(c.basePath)},
369
- endpoint: ${_q(c.endpoint)},
370
- channel: $channel,
456
+ bucketName: const String.fromEnvironment('AWS_BUCKET', defaultValue: ${_q(c.bucket ?? '')}),
457
+ region: const String.fromEnvironment('AWS_REGION', defaultValue: ${_q(c.region ?? '')}),
458
+ accessKeyId: const String.fromEnvironment('AWS_ACCESS_KEY_ID', defaultValue: ''),
459
+ secretAccessKey: const String.fromEnvironment('AWS_SECRET_ACCESS_KEY', defaultValue: ''),
460
+ basePath: const String.fromEnvironment('AWS_BASE_PATH', defaultValue: ${_q(c.basePath ?? '')}),
461
+ endpoint: const String.fromEnvironment('AWS_ENDPOINT', defaultValue: ${_q(c.endpoint ?? '')}),
462
+ channel: const String.fromEnvironment('CHANNEL', defaultValue: $channel),
371
463
  platform: Platform.android,
372
- updateStrategy: $strategy,
373
- appVersion: $appVersion,
464
+ updateStrategy: UpdateStrategy.appVersion,
465
+ appVersion: $appVersionExpr,
374
466
  ));''';
375
467
  case 'supabase':
376
468
  default:
377
469
  final c = cfg.supabase;
378
470
  configure = '''
379
471
  FlutterPatcher.configureSupabase(SupabaseUpdateConfig(
380
- supabaseUrl: ${_q(c.url)},
381
- anonKey: ${_q(c.anonKey)},
382
- bucket: ${_q(c.bucket ?? 'bundles')},
383
- channel: $channel,
472
+ supabaseUrl: const String.fromEnvironment('SUPABASE_URL', defaultValue: ${_q(c.url ?? '')}),
473
+ anonKey: const String.fromEnvironment('SUPABASE_ANON_KEY', defaultValue: ''),
474
+ bucket: const String.fromEnvironment('SUPABASE_BUCKET', defaultValue: ${_q(c.bucket ?? 'bundles')}),
475
+ channel: const String.fromEnvironment('CHANNEL', defaultValue: $channel),
384
476
  platform: Platform.android,
385
- updateStrategy: $strategy,
386
- appVersion: $appVersion,
387
- sdkVersion: '1.0.0',
477
+ updateStrategy: UpdateStrategy.appVersion,
478
+ appVersion: $appVersionExpr,
479
+ sdkVersion: const String.fromEnvironment('SDK_VERSION', defaultValue: '1.0.0'),
388
480
  ));''';
389
481
  }
390
482
 
391
483
  return '''
392
- import 'dart:io' show Platform;
393
-
394
484
  import 'package:flutter_ota_kit/flutter_ota_kit.dart';
395
485
 
396
486
  // Generated by `flutter_ota_kit init $provider`.
397
487
  //
398
- // Secrets are hard-coded here for a zero-config quick start. For production,
399
- // prefer reading them from --dart-define / environment variables instead.
488
+ // Non-secret values default to the project config (`.flutter_ota_kit/config.json`
489
+ // set up during init); every value can be overridden by a build-time
490
+ // `--dart-define` / `.env` (environment wins). Secrets (keys/tokens) are never
491
+ // hard-coded here — supply them via `.env`.
400
492
  //
401
493
  // Call [setupFlutterOta] once in `main()`, after
402
494
  // WidgetsFlutterBinding.ensureInitialized() and before runApp(). It wires the
@@ -12,9 +12,9 @@ import 'package:path/path.dart' as p;
12
12
  /// Resolved configuration for the flutter_ota_kit CLI.
13
13
  ///
14
14
  /// Mirrors hot-updater's config precedence: explicit flags > environment
15
- /// variables > the project `.otat/config.json` (falling back to the global
16
- /// `~/.otat/config.json`). All CLI working state lives under `.otat/` so it can
17
- /// be git-ignored as a single unit.
15
+ /// variables > the project `.flutter_ota_kit/config.json` (falling back to the
16
+ /// global `~/.flutter_ota_kit/config.json`). All CLI working state lives under
17
+ /// `.flutter_ota_kit/` so it can be git-ignored as a single unit.
18
18
  class FlutterPatcherConfig {
19
19
  FlutterPatcherConfig({
20
20
  required this.provider,
@@ -138,14 +138,14 @@ class SupabaseConfigJson {
138
138
  }
139
139
 
140
140
  /// Search order for a config file on disk. Both the project config and the
141
- /// global config live under a `.otat/` directory so all CLI state is grouped
142
- /// in one place (and can be git-ignored together).
141
+ /// global config live under a `.flutter_ota_kit/` directory so all CLI state is
142
+ /// grouped in one place (and can be git-ignored together).
143
143
  List<File> configCandidates() {
144
- final cwd = File(p.join(Directory.current.path, '.otat', 'config.json'));
144
+ final cwd = File(p.join(Directory.current.path, '.flutter_ota_kit', 'config.json'));
145
145
  final home = Platform.environment['HOME'] ??
146
146
  Platform.environment['USERPROFILE'] ??
147
147
  '';
148
- final global = File(p.join(home, '.otat', 'config.json'));
148
+ final global = File(p.join(home, '.flutter_ota_kit', 'config.json'));
149
149
  return [cwd, global];
150
150
  }
151
151
 
@@ -0,0 +1,3 @@
1
+ ## 0.1.0
2
+
3
+ - Initial release of `flutter_ota_kit_core` as part of the flutter_ota_kit OTA toolkit.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 xuelinger
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,23 @@
1
+ # flutter_ota_kit_core
2
+
3
+ Pure-Dart core of the [flutter_ota_kit](https://github.com/HYPER12755/flutter_ota_kit) OTA toolkit. It has **no Flutter dependency** and is shared by every other package (client, plugin-core, and all four backends).
4
+
5
+ ## What's inside
6
+
7
+ - **Data model** — `Bundle`, `PatchInfo`, `AppUpdateInfo`, and the `Platform` / `UpdateStrategy` / status enums that describe an over-the-air update.
8
+ - **Rollout math** — deterministic staged-rollout cohort helpers (`rollout.dart`).
9
+ - **Semver** — `semverSatisfies(target, range)` for matching a device's app version against a bundle's rollout rule.
10
+ - **Identifiers** — `uuidv7` generation plus a `NIL` sentinel (`uuid.dart`).
11
+ - **Bundle artifacts** — helpers to describe and address content-addressed patch artifacts.
12
+
13
+ ## Usage
14
+
15
+ ```dart
16
+ import 'package:flutter_ota_kit_core/flutter_ota_kit_core.dart';
17
+
18
+ final ok = semverSatisfies('1.0.0', '>=1.0.0 <2.0.0'); // true
19
+ ```
20
+
21
+ ## License
22
+
23
+ MIT — see the [project LICENSE](https://github.com/HYPER12755/flutter_ota_kit/blob/main/LICENSE).
@@ -1,7 +1,12 @@
1
1
  name: flutter_ota_kit_core
2
2
  description: Core data model, rollout cohorts, and shared utilities for flutter_ota_kit — Dart translation of hot-updater's packages/core.
3
3
  version: 0.1.0
4
- publish_to: none
4
+ publish_to: https://pub.dev
5
+ homepage: https://github.com/HYPER12755/flutter_ota_kit
6
+ repository: https://github.com/HYPER12755/flutter_ota_kit
7
+ issue_tracker: https://github.com/HYPER12755/flutter_ota_kit/issues
8
+ documentation: https://github.com/HYPER12755/flutter_ota_kit#readme
9
+ license: MIT
5
10
 
6
11
  environment:
7
12
  sdk: '>=3.0.0 <4.0.0'
@@ -0,0 +1,3 @@
1
+ ## 0.1.0
2
+
3
+ - Initial release of `flutter_ota_kit_aws` as part of the flutter_ota_kit OTA toolkit.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 xuelinger
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,28 @@
1
+ # flutter_ota_kit_aws
2
+
3
+ AWS backend for flutter_ota_kit: bundle metadata in an **S3-backed blob
4
+ database** and artifacts in **S3** (with optional CloudFront signed URLs). Used
5
+ by the `flutter-ota` CLI and the Flutter SDK's `FlutterPatcher.configureAws(...)`.
6
+
7
+ ## What's inside
8
+
9
+ - `s3Database` / `S3DatabaseConfig` — bundle metadata stored as S3 objects.
10
+ - `s3Storage` / `AwsS3StorageConfig` — artifact storage in S3.
11
+ - CloudFront signed URLs: `cloudfrontSignedUrl`, `verifyCloudfrontSignedUrl`,
12
+ and `withCloudFrontSignedUrl(...)`.
13
+ - `AwsS3ClientLike` / `AwsCloudFrontClientLike` test seams.
14
+
15
+ ## Configuration (environment)
16
+
17
+ | Variable | Purpose |
18
+ | --- | --- |
19
+ | `AWS_REGION` | S3 region (falls back to `AWS_REGION`/`AWS_DEFAULT_REGION` if unset). |
20
+ | `AWS_BUCKET` | Target bucket name. |
21
+ | `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY` | Credentials. |
22
+ | `AWS_ENDPOINT` | Optional custom endpoint (e.g. MinIO). |
23
+ | `AWS_BASE_PATH` | Optional key prefix. |
24
+ | `AWS_SESSION_TOKEN` | Optional temporary session token. |
25
+
26
+ ## License
27
+
28
+ MIT.
@@ -1,16 +1,19 @@
1
1
  name: flutter_ota_kit_aws
2
2
  description: AWS S3 storage + S3/DynamoDB database plugins for flutter_ota_kit (faithful port of hot-updater plugins/aws).
3
3
  version: 0.1.0
4
- publish_to: none
4
+ publish_to: https://pub.dev
5
+ homepage: https://github.com/HYPER12755/flutter_ota_kit
6
+ repository: https://github.com/HYPER12755/flutter_ota_kit
7
+ issue_tracker: https://github.com/HYPER12755/flutter_ota_kit/issues
8
+ documentation: https://github.com/HYPER12755/flutter_ota_kit#readme
9
+ license: MIT
5
10
 
6
11
  environment:
7
12
  sdk: ">=3.3.0 <4.0.0"
8
13
 
9
14
  dependencies:
10
- flutter_ota_kit_core:
11
- path: ../../packages/core
12
- flutter_ota_kit_plugin_core:
13
- path: ../../plugins/plugin-core
15
+ flutter_ota_kit_core: ^0.1.0
16
+ flutter_ota_kit_plugin_core: ^0.0.1
14
17
  crypto: ^3.0.0
15
18
  http: ^1.2.0
16
19
  path: ^1.9.0
@@ -0,0 +1,3 @@
1
+ ## 0.1.0
2
+
3
+ - Initial release of `flutter_ota_kit_cloudflare` as part of the flutter_ota_kit OTA toolkit.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 xuelinger
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,25 @@
1
+ # flutter_ota_kit_cloudflare
2
+
3
+ Cloudflare backend for flutter_ota_kit: bundle metadata in **D1** (SQLite-at-edge)
4
+ and artifacts in **R2** (S3-compatible storage). Used by the `flutter-ota` CLI and
5
+ the Flutter SDK's `FlutterPatcher.configureCloudflare(...)`.
6
+
7
+ ## What's inside
8
+
9
+ - `d1Database` / `D1DatabaseConfig` — bundle metadata in D1.
10
+ `CloudflareWorkerDatabaseConfig` / `cloudflareWorkerDatabase` for the
11
+ Worker-facing variant.
12
+ - `r2Storage` / `R2S3StorageConfig` — artifact storage in R2 (AWS SigV4).
13
+ - D1 row mappers and `D1ClientFactory` / `R2S3ClientFactory` test seams.
14
+
15
+ ## Configuration (environment)
16
+
17
+ | Variable | Purpose |
18
+ | --- | --- |
19
+ | `CLOUDFLARE_ACCOUNT_ID` | Cloudflare account id. |
20
+ | `CLOUDFLARE_API_TOKEN` | API token with D1 read/write + R2 permissions. |
21
+ | R2 access/secret keys + bucket | Supplied via `R2S3StorageConfig` (see the CLI `init` and `doc/backends.md`). |
22
+
23
+ ## License
24
+
25
+ MIT.
@@ -1,16 +1,19 @@
1
1
  name: flutter_ota_kit_cloudflare
2
2
  description: Cloudflare D1 + R2 storage plugins for flutter_ota_kit (faithful port of hot-updater plugins/cloudflare).
3
3
  version: 0.1.0
4
- publish_to: none
4
+ publish_to: https://pub.dev
5
+ homepage: https://github.com/HYPER12755/flutter_ota_kit
6
+ repository: https://github.com/HYPER12755/flutter_ota_kit
7
+ issue_tracker: https://github.com/HYPER12755/flutter_ota_kit/issues
8
+ documentation: https://github.com/HYPER12755/flutter_ota_kit#readme
9
+ license: MIT
5
10
 
6
11
  environment:
7
12
  sdk: ">=3.3.0 <4.0.0"
8
13
 
9
14
  dependencies:
10
- flutter_ota_kit_core:
11
- path: ../../packages/core
12
- flutter_ota_kit_plugin_core:
13
- path: ../../plugins/plugin-core
15
+ flutter_ota_kit_core: ^0.1.0
16
+ flutter_ota_kit_plugin_core: ^0.0.1
14
17
  crypto: ^3.0.0
15
18
  http: ^1.2.0
16
19
  path: ^1.9.0
@@ -0,0 +1,3 @@
1
+ ## 0.0.1
2
+
3
+ - Initial release of `flutter_ota_kit_plugin_core` as part of the flutter_ota_kit OTA toolkit.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 xuelinger
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,21 @@
1
+ # flutter_ota_kit_plugin_core
2
+
3
+ Internal plugin abstractions shared by the flutter_ota_kit backend plugins
4
+ (`flutter_ota_kit_supabase`, `flutter_ota_kit_postgres`,
5
+ `flutter_ota_kit_cloudflare`, `flutter_ota_kit_aws`).
6
+
7
+ ## What's inside
8
+
9
+ - The `Database`, `Storage`, and build interfaces that each backend implements.
10
+ - Factory helpers: `createDatabasePlugin`, `createStoragePlugin`,
11
+ `createBlobDatabasePlugin`.
12
+ - Pagination, content-addressed asset addressing, and storage/bundle layout
13
+ helpers used to keep all backends wire-compatible with the same bundle schema.
14
+
15
+ This package is a building block for the concrete backends and the `flutter-ota`
16
+ CLI; application code normally consumes the higher-level `flutter_ota_kit` API
17
+ instead.
18
+
19
+ ## License
20
+
21
+ MIT.
@@ -1,13 +1,18 @@
1
1
  name: flutter_ota_kit_plugin_core
2
2
  description: Plugin core abstractions for flutter_ota_kit — database, storage, and build interfaces.
3
3
  version: 0.0.1
4
+ publish_to: https://pub.dev
5
+ homepage: https://github.com/HYPER12755/flutter_ota_kit
6
+ repository: https://github.com/HYPER12755/flutter_ota_kit
7
+ issue_tracker: https://github.com/HYPER12755/flutter_ota_kit/issues
8
+ documentation: https://github.com/HYPER12755/flutter_ota_kit#readme
9
+ license: MIT
4
10
 
5
11
  environment:
6
12
  sdk: ">=3.3.0 <4.0.0"
7
13
 
8
14
  dependencies:
9
- flutter_ota_kit_core:
10
- path: ../../packages/core
15
+ flutter_ota_kit_core: ^0.1.0
11
16
  mime: ^1.0.0
12
17
 
13
18
  dev_dependencies:
@@ -0,0 +1,3 @@
1
+ ## 0.1.0
2
+
3
+ - Initial release of `flutter_ota_kit_postgres` as part of the flutter_ota_kit OTA toolkit.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 xuelinger
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,29 @@
1
+ # flutter_ota_kit_postgres
2
+
3
+ Postgres backend for flutter_ota_kit: bundle metadata in a Postgres database and
4
+ artifacts in the bytea-backed storage plugin. Used by the `flutter-ota` CLI and
5
+ the Flutter SDK's `FlutterPatcher.configurePostgres(...)`.
6
+
7
+ ## What's inside
8
+
9
+ - `postgresDatabase` / `PostgresConfig` — bundle read/write over a Postgres
10
+ connection.
11
+ - `postgresStorage` / `PostgresStorageConfig` / `resolvePostgresStorageClient` —
12
+ artifact storage.
13
+ - `getUpdateInfo` — resolve the latest applicable bundle for a device.
14
+ - Row mappers (`PostgresBundleRow`, `PostgresBundlePatchRow`,
15
+ `bundleToRowValues`, `bundleToPatchRows`) for the `bundles` / `bundle_patches`
16
+ tables.
17
+
18
+ ## Configuration (environment)
19
+
20
+ | Variable | Purpose |
21
+ | --- | --- |
22
+ | `DATABASE_URL` | Full Postgres connection string (preferred). |
23
+ | `POSTGRES_HOST` / `POSTGRES_PORT` / `POSTGRES_DB` / `POSTGRES_USER` / `POSTGRES_PASSWORD` / `POSTGRES_SSLMODE` | Individual connection fields. |
24
+ | `POSTGRES_SERVING_BASE_URL` | HTTP proxy/base URL in front of the storage table for artifact downloads. |
25
+ | `POSTGRES_BASE_PATH` | Optional object-key prefix. |
26
+
27
+ ## License
28
+
29
+ MIT.
@@ -1,16 +1,19 @@
1
1
  name: flutter_ota_kit_postgres
2
2
  description: Postgres plugin for flutter_ota_kit — database backend.
3
3
  version: 0.1.0
4
- publish_to: none
4
+ publish_to: https://pub.dev
5
+ homepage: https://github.com/HYPER12755/flutter_ota_kit
6
+ repository: https://github.com/HYPER12755/flutter_ota_kit
7
+ issue_tracker: https://github.com/HYPER12755/flutter_ota_kit/issues
8
+ documentation: https://github.com/HYPER12755/flutter_ota_kit#readme
9
+ license: MIT
5
10
 
6
11
  environment:
7
12
  sdk: ">=3.3.0 <4.0.0"
8
13
 
9
14
  dependencies:
10
- flutter_ota_kit_core:
11
- path: ../../packages/core
12
- flutter_ota_kit_plugin_core:
13
- path: ../../plugins/plugin-core
15
+ flutter_ota_kit_core: ^0.1.0
16
+ flutter_ota_kit_plugin_core: ^0.0.1
14
17
  postgres: ^3.4.0
15
18
 
16
19
  dev_dependencies:
@@ -0,0 +1,3 @@
1
+ ## 0.1.0
2
+
3
+ - Initial release of `flutter_ota_kit_supabase` as part of the flutter_ota_kit OTA toolkit.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 xuelinger
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,53 @@
1
+ # flutter_ota_kit_supabase
2
+
3
+ Supabase backend for [flutter_ota_kit](https://github.com/HYPER12755/flutter_ota_kit).
4
+ Implements the bundle **database** (PostgREST `bundles` table) and **storage**
5
+ (signed URLs) used both by the `flutter-ota` CLI and by the Flutter SDK's
6
+ `FlutterPatcher.configureSupabase(...)`.
7
+
8
+ ## What's inside
9
+
10
+ - `supabaseDatabase` / `SupabaseDatabaseConfig` — read/update bundles over the
11
+ Supabase REST (PostgREST) API.
12
+ - `supabaseStorage` / `SupabaseStorageConfig` / `parseSupabaseStorageUri` —
13
+ resolve presigned download URLs.
14
+ - Edge-function variants: `supabaseEdgeFunctionDatabase`,
15
+ `supabaseEdgeFunctionStorage` (extra security boundary via a Supabase Edge
16
+ Function instead of direct client access).
17
+ - `SupabaseClientFactory` / `createSupabaseHttpClient` — test seams / custom
18
+ HTTP clients.
19
+ - `SupabaseServiceRoleConfig` — holds the service-role or anon key with a
20
+ `resolveKey()` helper.
21
+
22
+ ## Configuration (environment)
23
+
24
+ | Variable | Purpose |
25
+ | --- | --- |
26
+ | `SUPABASE_URL` | Project REST URL (`https://<ref>.supabase.co`). |
27
+ | `SUPABASE_ANON_KEY` | Public anon key (RLS-protected reads). |
28
+ | `SUPABASE_SERVICE_ROLE_KEY` | Service-role key (migrations / writes). |
29
+ | `SUPABASE_BUCKET` | Storage bucket holding patch artifacts. |
30
+ | `SUPABASE_BASE_PATH` | Optional prefix for stored objects. |
31
+ | `SUPABASE_DATABASE_URL` | Connection string for migrations (alternative). |
32
+
33
+ ## Usage (Flutter SDK)
34
+
35
+ ```dart
36
+ import 'package:flutter_ota_kit/flutter_ota_kit.dart';
37
+
38
+ FlutterPatcher.configureSupabase(SupabaseUpdateConfig(
39
+ supabaseUrl: 'https://<ref>.supabase.co',
40
+ anonKey: '<anon>',
41
+ bucket: 'bundles',
42
+ channel: 'production',
43
+ platform: Platform.android,
44
+ updateStrategy: UpdateStrategy.appVersion,
45
+ appVersion: '1.0.0',
46
+ ));
47
+ ```
48
+
49
+ See [doc/backends.md](https://github.com/HYPER12755/flutter_ota_kit/blob/main/doc/backends.md).
50
+
51
+ ## License
52
+
53
+ MIT.
@@ -1,16 +1,19 @@
1
1
  name: flutter_ota_kit_supabase
2
2
  description: Supabase plugin for flutter_ota_kit — database + storage backends.
3
- version: 0.1.0
4
- publish_to: none
3
+ version: 0.1.1
4
+ publish_to: https://pub.dev
5
+ homepage: https://github.com/HYPER12755/flutter_ota_kit
6
+ repository: https://github.com/HYPER12755/flutter_ota_kit
7
+ issue_tracker: https://github.com/HYPER12755/flutter_ota_kit/issues
8
+ documentation: https://github.com/HYPER12755/flutter_ota_kit#readme
9
+ license: MIT
5
10
 
6
11
  environment:
7
12
  sdk: ">=3.3.0 <4.0.0"
8
13
 
9
14
  dependencies:
10
- flutter_ota_kit_core:
11
- path: ../../packages/core
12
- flutter_ota_kit_plugin_core:
13
- path: ../../plugins/plugin-core
15
+ flutter_ota_kit_core: ^0.1.0
16
+ flutter_ota_kit_plugin_core: ^0.0.1
14
17
  http: ^1.2.0
15
18
  supabase: ^2.14.0
16
19
 
@@ -46,3 +46,14 @@ ALTER FUNCTION public.get_update_info_by_app_version(
46
46
  text
47
47
  )
48
48
  SET search_path = public, pg_catalog;
49
+
50
+ -- OTA update checks are unauthenticated by design (the device only carries the
51
+ -- anon key), so bundle metadata must be publicly readable. hot-updater's hosted
52
+ -- Supabase flow relies on these policies existing.
53
+ CREATE POLICY "allow public read bundles" ON public.bundles FOR SELECT USING (true);
54
+ CREATE POLICY "allow public read bundle_patches" ON public.bundle_patches FOR SELECT USING (true);
55
+
56
+ -- Allow anon/authenticated to resolve signed download URLs for the bundles bucket.
57
+ CREATE POLICY "public bundles read" ON storage.objects
58
+ FOR SELECT TO anon, authenticated
59
+ USING (bucket_id = 'bundles');
@@ -46,3 +46,14 @@ ALTER FUNCTION public.get_update_info_by_app_version(
46
46
  text
47
47
  )
48
48
  SET search_path = public, pg_catalog;
49
+
50
+ -- OTA update checks are unauthenticated by design (the device only carries the
51
+ -- anon key), so bundle metadata must be publicly readable. hot-updater's hosted
52
+ -- Supabase flow relies on these policies existing.
53
+ CREATE POLICY "allow public read bundles" ON public.bundles FOR SELECT USING (true);
54
+ CREATE POLICY "allow public read bundle_patches" ON public.bundle_patches FOR SELECT USING (true);
55
+
56
+ -- Allow anon/authenticated to resolve signed download URLs for the bundles bucket.
57
+ CREATE POLICY "public bundles read" ON storage.objects
58
+ FOR SELECT TO anon, authenticated
59
+ USING (bucket_id = 'bundles');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@_nazmiforreal/flutter-ota",
3
- "version": "0.1.8",
3
+ "version": "0.1.10",
4
4
  "description": "Command-line interface for flutter_ota_kit — an OTA code-push tool for Flutter, hot-updater compatible.",
5
5
  "bin": {
6
6
  "flutter-ota": "./bin/flutter-ota.js"