@_nazmiforreal/flutter-ota 0.1.17 → 0.1.19

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.
Binary file
@@ -204,19 +204,10 @@ class BundleDeleteCommand extends FlutterPatcherCommand {
204
204
  }
205
205
  final keepStorage = argResults!['keep-storage'] as bool;
206
206
  final steps = Steps('delete');
207
- await spinner(
208
- () => deleteBundle(backend, id),
209
- 'Deleting bundle $id',
210
- done: 'Deleted',
211
- );
212
- steps.success('Deleted bundle $id');
207
+ await steps.run('Deleting bundle $id', () => deleteBundle(backend, id));
213
208
  if (!keepStorage && existing.storageUri.isNotEmpty) {
214
- await spinner(
215
- () => backend.storage.delete(existing.storageUri),
216
- 'Removing storage object',
217
- done: 'Storage removed',
218
- );
219
- steps.success('Removed storage object');
209
+ await steps.run('Removing storage object',
210
+ () => backend.storage.delete(existing.storageUri));
220
211
  }
221
212
  steps.summary();
222
213
  });
@@ -244,14 +235,12 @@ class BundleDisableCommand extends FlutterPatcherCommand {
244
235
  final cfg = effectiveConfig(config ?? loadConfig(), argResults!);
245
236
  final backend = requireBackend(cfg, override: backendOverride);
246
237
  banner('bundle · disable');
247
- await spinner(
248
- () async {
249
- await backend.db.updateBundle(id!, {'enabled': false});
250
- await backend.db.commitBundle();
251
- },
252
- 'Disabling bundle $id',
253
- done: 'Disabled',
254
- );
238
+ final steps = Steps('disable');
239
+ await steps.run('Disabling bundle $id', () async {
240
+ await backend.db.updateBundle(id!, {'enabled': false});
241
+ await backend.db.commitBundle();
242
+ });
243
+ steps.summary();
255
244
  });
256
245
  }
257
246
 
@@ -277,14 +266,12 @@ class BundleEnableCommand extends FlutterPatcherCommand {
277
266
  final cfg = effectiveConfig(config ?? loadConfig(), argResults!);
278
267
  final backend = requireBackend(cfg, override: backendOverride);
279
268
  banner('bundle · enable');
280
- await spinner(
281
- () async {
282
- await backend.db.updateBundle(id!, {'enabled': true});
283
- await backend.db.commitBundle();
284
- },
285
- 'Enabling bundle $id',
286
- done: 'Enabled',
287
- );
269
+ final steps = Steps('enable');
270
+ await steps.run('Enabling bundle $id', () async {
271
+ await backend.db.updateBundle(id!, {'enabled': true});
272
+ await backend.db.commitBundle();
273
+ });
274
+ steps.summary();
288
275
  });
289
276
  }
290
277
 
@@ -315,7 +302,9 @@ class BundleForceCommand extends FlutterPatcherCommand {
315
302
  final cfg = effectiveConfig(config ?? loadConfig(), argResults!);
316
303
  final backend = requireBackend(cfg, override: backendOverride);
317
304
  banner('bundle · force');
318
- await spinner(
305
+ final steps = Steps('force');
306
+ await steps.run(
307
+ off ? 'Clearing force flag on $id' : 'Forcing update for $id',
319
308
  () async {
320
309
  await backend.db.updateBundle(id!, {
321
310
  'shouldForceUpdate': !off,
@@ -323,9 +312,8 @@ class BundleForceCommand extends FlutterPatcherCommand {
323
312
  });
324
313
  await backend.db.commitBundle();
325
314
  },
326
- off ? 'Clearing force flag on $id' : 'Forcing update for $id',
327
- done: off ? 'Cleared' : 'Forced',
328
315
  );
316
+ steps.summary();
329
317
  });
330
318
  }
331
319
 
@@ -359,11 +347,10 @@ class BundlePromoteCommand extends FlutterPatcherCommand {
359
347
  final cfg = effectiveConfig(config ?? loadConfig(), argResults!);
360
348
  final backend = requireBackend(cfg, override: backendOverride);
361
349
  banner('bundle · promote');
362
- await spinner(
363
- () => promoteBundle(backend, id!, channel),
364
- 'Promoting $id to $channel',
365
- done: 'Promoted',
366
- );
350
+ final steps = Steps('promote');
351
+ await steps.run('Promoting $id to $channel',
352
+ () => promoteBundle(backend, id!, channel));
353
+ steps.summary();
367
354
  box('promote', [kv('bundle', cyan(id!)), kv('channel', channel)]);
368
355
  });
369
356
  }
@@ -411,15 +398,13 @@ class BundleUpdateCommand extends FlutterPatcherCommand {
411
398
  final cfg = effectiveConfig(config ?? loadConfig(), argResults!);
412
399
  final backend = requireBackend(cfg, override: backendOverride);
413
400
  banner('bundle · update');
414
- await spinner(
415
- () async {
416
- await backend.db.updateBundle(id!, patch);
417
- await backend.db.commitBundle();
418
- },
419
- 'Updating $id',
420
- done: 'Updated',
421
- );
401
+ final steps = Steps('update');
402
+ await steps.run('Updating $id', () async {
403
+ await backend.db.updateBundle(id!, patch);
404
+ await backend.db.commitBundle();
405
+ });
422
406
  final b = await backend.db.getBundleById(id!);
407
+ steps.summary();
423
408
  if (b != null) {
424
409
  box('bundle', [
425
410
  kv('id', cyan(b.id)),
@@ -130,11 +130,10 @@ class ChannelSetCommand extends FlutterPatcherCommand {
130
130
  }
131
131
  final backend = requireBackend(cfg, override: backendOverride);
132
132
  banner('channel · set');
133
- await spinner(
134
- () => promoteBundle(backend, bundleId, channel),
135
- 'Promoting $bundleId to $channel',
136
- done: 'Channel set',
137
- );
133
+ final steps = Steps('set');
134
+ await steps.run('Promoting $bundleId to $channel',
135
+ () => promoteBundle(backend, bundleId, channel));
136
+ steps.summary();
138
137
  box('channel set', [kv('channel', channel), kv('bundle', cyan(bundleId))]);
139
138
  });
140
139
  }
@@ -1,5 +1,7 @@
1
1
  import 'dart:io';
2
2
 
3
+ import 'package:flutter_ota_kit_core/flutter_ota_kit_core.dart';
4
+
3
5
  import '../backend.dart';
4
6
  import '../cli_base.dart';
5
7
  import '../config.dart';
@@ -75,25 +77,11 @@ class DeployCommand extends FlutterPatcherCommand {
75
77
  banner('deploy');
76
78
  info('channel ${cyan(channel)} platform ${cyan(platform)} source ${dim(source)}');
77
79
 
78
- final bundle = await spinner(
79
- () => deployBundle(
80
- backend,
81
- DeployOptions(
82
- source: source,
83
- channel: channel,
84
- platform: platform,
85
- message: message,
86
- force: force,
87
- targetAppVersion: targetAppVersion,
88
- fingerprintHash: fingerprintHash,
89
- signingKeyBase64: signingKey,
90
- gitCommitHash: resolvedGitCommitHash,
91
- bundleId: bundleId,
92
- ),
93
- ),
94
- 'Uploading & registering bundle',
95
- done: 'Bundle deployed',
96
- );
80
+ final steps = Steps('deploy');
81
+ final bundle = await _deployWithPhases(steps, backend, source, channel,
82
+ platform, message, force, targetAppVersion, fingerprintHash,
83
+ signingKey, resolvedGitCommitHash, bundleId);
84
+ steps.summary();
97
85
 
98
86
  final lines = <String>[
99
87
  kv('bundle id', cyan(bundle.id)),
@@ -118,3 +106,57 @@ class DeployCommand extends FlutterPatcherCommand {
118
106
  box('deployed', lines);
119
107
  });
120
108
  }
109
+
110
+ /// Deploy with per-phase UI. Each phase reported by `DeployOptions.onPhase`
111
+ /// is shown as an active spinner line that gets replaced in-place.
112
+ Future<Bundle> _deployWithPhases(
113
+ Steps steps,
114
+ Backend backend,
115
+ String source,
116
+ String channel,
117
+ String platform,
118
+ String? message,
119
+ bool force,
120
+ String? targetAppVersion,
121
+ String? fingerprintHash,
122
+ String? signingKey,
123
+ String? resolvedGitCommitHash,
124
+ String? bundleId,
125
+ ) async {
126
+ String? activeLabel;
127
+ try {
128
+ final bundle = await deployBundle(
129
+ backend,
130
+ DeployOptions(
131
+ source: source,
132
+ channel: channel,
133
+ platform: platform,
134
+ message: message,
135
+ force: force,
136
+ targetAppVersion: targetAppVersion,
137
+ fingerprintHash: fingerprintHash,
138
+ signingKeyBase64: signingKey,
139
+ gitCommitHash: resolvedGitCommitHash,
140
+ bundleId: bundleId,
141
+ onPhase: (phase) {
142
+ if (activeLabel != null) {
143
+ steps.completeActive();
144
+ }
145
+ activeLabel = phase;
146
+ steps.startActive(phase);
147
+ },
148
+ ),
149
+ );
150
+ if (activeLabel != null) {
151
+ steps.completeActive();
152
+ activeLabel = null;
153
+ }
154
+ return bundle;
155
+ } catch (e) {
156
+ if (activeLabel != null) {
157
+ steps.completeActive(success: false);
158
+ activeLabel = null;
159
+ }
160
+ rethrow;
161
+ }
162
+ }
@@ -21,10 +21,11 @@ class KeysCommand extends FlutterPatcherCommand {
21
21
  @override
22
22
  Future<int> run() => runGuarded(() async {
23
23
  banner('keys');
24
- final (privateB64, publicB64) = await spinner(
25
- () => generateEd25519KeyPair(),
24
+ final steps = Steps('keys');
25
+ final (privateB64, publicB64) = await steps.run(
26
26
  'Generating Ed25519 keypair',
27
- done: 'Keypair generated',
27
+ () => generateEd25519KeyPair(),
28
+ // Use Steps.run without the spinner pattern; keys is fast.
28
29
  );
29
30
  box('ed25519 keys', [
30
31
  '${bold('private')} (keep secret — use with `deploy --key`):',
@@ -37,12 +38,15 @@ class KeysCommand extends FlutterPatcherCommand {
37
38
  final file = configCandidates().first;
38
39
  final json =
39
40
  file.existsSync() && file.readAsStringSync().trim().isNotEmpty
40
- ? (jsonDecode(file.readAsStringSync()) as Map<String, dynamic>)
41
- : <String, dynamic>{};
41
+ ? (jsonDecode(file.readAsStringSync()) as Map<String, dynamic>)
42
+ : <String, dynamic>{};
42
43
  writePath(json, 'publicKey', publicB64);
43
- _save(json);
44
- step('Saved public key to ${file.path}');
44
+ await steps.run<void>('Saving public key to ${file.path}',
45
+ () async {
46
+ _save(json);
47
+ });
45
48
  }
49
+ steps.summary();
46
50
  });
47
51
 
48
52
  void _save(Map<String, dynamic> json) {
@@ -45,23 +45,21 @@ class RollbackCommand extends FlutterPatcherCommand {
45
45
  final backend = requireBackend(cfg, override: backendOverride);
46
46
 
47
47
  banner('rollback');
48
- final (disabled, live) = await spinner(
49
- () async {
50
- if (bundleId != null && bundleId.isNotEmpty) {
51
- return rollbackToBundle(
52
- backend,
53
- channel,
54
- bundleId,
55
- platform: platform,
56
- );
57
- }
58
- final id = await rollbackChannel(backend, channel);
59
- final nowLive = (await getChannel(backend, channel))?.id ?? '';
60
- return (<String>[id], nowLive);
61
- },
62
- 'Rolling back channel "$channel"',
63
- done: 'Rolled back',
64
- );
48
+ final steps = Steps('rollback');
49
+ final (disabled, live) = await steps.run('Rolling back channel "$channel"', () async {
50
+ if (bundleId != null && bundleId.isNotEmpty) {
51
+ return rollbackToBundle(
52
+ backend,
53
+ channel,
54
+ bundleId,
55
+ platform: platform,
56
+ );
57
+ }
58
+ final id = await rollbackChannel(backend, channel);
59
+ final nowLive = (await getChannel(backend, channel))?.id ?? '';
60
+ return (<String>[id], nowLive);
61
+ });
62
+ steps.summary();
65
63
  box('rollback', [
66
64
  kv('channel', channel),
67
65
  kv('now live', live.isEmpty ? dim('(none)') : cyan(live)),
@@ -46,11 +46,13 @@ class StorageListCommand extends FlutterPatcherCommand {
46
46
  final backend = requireBackend(cfg, override: backendOverride);
47
47
  final prefix = argResults!['prefix'] as String?;
48
48
  banner('storage · list');
49
- final objects = await backend.storage.listObjects(
50
- prefix == null || prefix.isEmpty ? null : prefix,
51
- );
49
+ final steps = Steps('list');
50
+ final objects = await steps.run('Listing storage objects', () =>
51
+ backend.storage.listObjects(
52
+ prefix == null || prefix.isEmpty ? null : prefix));
52
53
  if (objects.isEmpty) {
53
- step('(no objects)');
54
+ steps.skip('(no objects)');
55
+ steps.summary();
54
56
  return;
55
57
  }
56
58
  final rows = <List<String>>[];
@@ -58,11 +60,12 @@ class StorageListCommand extends FlutterPatcherCommand {
58
60
  final size = o.size >= 1024 * 1024
59
61
  ? '${(o.size / (1024 * 1024)).toStringAsFixed(2)} MB'
60
62
  : o.size >= 1024
61
- ? '${(o.size / 1024).toStringAsFixed(1)} KB'
62
- : '${o.size} B';
63
+ ? '${(o.size / 1024).toStringAsFixed(1)} KB'
64
+ : '${o.size} B';
63
65
  rows.add([cyan(o.key), size]);
64
66
  }
65
67
  table('${objects.length} objects', ['KEY', 'SIZE'], rows);
68
+ steps.summary();
66
69
  });
67
70
  }
68
71
 
@@ -96,18 +99,13 @@ class StorageDeleteCommand extends FlutterPatcherCommand {
96
99
  final cfg = effectiveConfig(config ?? loadConfig(), argResults!);
97
100
  final backend = requireBackend(cfg, override: backendOverride);
98
101
  banner('storage · delete');
102
+ final steps = Steps('delete');
99
103
  if (keys.isNotEmpty) {
100
- await spinner(
101
- () => backend.storage.deleteObjects(keys),
102
- 'Deleting ${keys.length} object(s)',
103
- done: 'Deleted',
104
- );
104
+ await steps.run('Deleting ${keys.length} object(s)',
105
+ () => backend.storage.deleteObjects(keys));
105
106
  } else {
106
- await spinner(
107
- () => backend.storage.delete(uri!),
108
- 'Deleting $uri',
109
- done: 'Deleted',
110
- );
107
+ await steps.run('Deleting $uri', () => backend.storage.delete(uri!));
111
108
  }
109
+ steps.summary();
112
110
  });
113
111
  }
@@ -23,6 +23,7 @@ class DeployOptions {
23
23
  this.gitCommitHash,
24
24
  this.bundleId,
25
25
  this.metadata,
26
+ this.onPhase,
26
27
  });
27
28
 
28
29
  final String source;
@@ -36,6 +37,10 @@ class DeployOptions {
36
37
  final String? gitCommitHash;
37
38
  final String? bundleId;
38
39
  final BundleMetadata? metadata;
40
+
41
+ /// Called with a human-readable phase label as deploy progresses.
42
+ /// Used by the CLI to show per-step progress (e.g. Steps.run()).
43
+ final void Function(String phase)? onPhase;
39
44
  }
40
45
 
41
46
  /// Options for [listBundles].
@@ -85,6 +90,7 @@ Future<Bundle> deployBundle(Backend backend, DeployOptions opts) async {
85
90
  zipPath = packaged.path;
86
91
  shouldDelete = false;
87
92
  } else {
93
+ opts.onPhase?.call('Zipping source');
88
94
  zipPath = await zipDirectory(opts.source);
89
95
  shouldDelete = true;
90
96
  }
@@ -94,6 +100,7 @@ Future<Bundle> deployBundle(Backend backend, DeployOptions opts) async {
94
100
  final zipBytes = await File(zipPath).readAsBytes();
95
101
  // Device SDK verifies the artifact against an MD5 hex of the whole file,
96
102
  // so `fileHash` is always the MD5 hex (never a `sig:`-prefixed value).
103
+ opts.onPhase?.call('Hashing artifact');
97
104
  final md5Hex = md5.convert(zipBytes).toString();
98
105
  final signature = opts.signingKeyBase64 != null
99
106
  ? await ed25519Sign(utf8.encode(md5Hex), opts.signingKeyBase64!)
@@ -101,6 +108,7 @@ Future<Bundle> deployBundle(Backend backend, DeployOptions opts) async {
101
108
 
102
109
  final bundleId = opts.bundleId ?? uuidV7();
103
110
  final key = bundleId;
111
+ opts.onPhase?.call('Uploading to storage');
104
112
  final uploaded = await backend.storage.upload(key, zipPath);
105
113
  final storageUri = uploaded['storageUri'];
106
114
  if (storageUri == null || storageUri.isEmpty) {
@@ -125,6 +133,7 @@ Future<Bundle> deployBundle(Backend backend, DeployOptions opts) async {
125
133
  rolloutCohortCount: defaultRolloutCohortCount,
126
134
  );
127
135
 
136
+ opts.onPhase?.call('Registering bundle in database');
128
137
  await backend.db.appendBundle(bundle);
129
138
  await backend.db.commitBundle();
130
139
  return bundle;
@@ -302,11 +302,115 @@ class Steps {
302
302
  final parts = <String>[];
303
303
  if (_done > 0) parts.add('${_done} completed');
304
304
  if (_skipped > 0) parts.add('${_skipped} skipped');
305
- if (_failed > 0) parts.add('${red('${_failed} error${_failed > 1 ? 's' : ''}')}');
305
+ if (_failed > 0) {
306
+ parts.add('${red('${_failed} error${_failed > 1 ? 's' : ''}')}');
307
+ }
306
308
  if (parts.isEmpty) parts.add('no steps');
307
309
  parts.add(time);
308
310
  box('summary', [parts.join(' · ')]);
309
311
  }
312
+
313
+ /// Run a step that shows a spinner while working, then marks it
314
+ /// success/fail/skip based on the result. This is the recommended way to
315
+ /// show multi-phase work where each phase has a distinct label the user
316
+ /// can understand.
317
+ ///
318
+ /// Example:
319
+ /// ```dart
320
+ /// final s = Steps('deploy');
321
+ /// final zipped = await s.run('Zipping source', () async {
322
+ /// return await zipDir(source);
323
+ /// });
324
+ /// final uploaded = await s.run('Uploading to storage', () async {
325
+ /// return await backend.putObject(bucket, zipped);
326
+ /// });
327
+ /// await s.run('Registering bundle', () async {
328
+ /// return await backend.insertBundle(...);
329
+ /// });
330
+ /// s.summary();
331
+ /// ```
332
+ Future<T> run<T>(String label, Future<T> Function() task) async {
333
+ if (!_colorOn) {
334
+ _echo(' ${dim('•')} $label');
335
+ try {
336
+ final r = await task();
337
+ _done++;
338
+ _echo(' ${green('✓')} $label');
339
+ return r;
340
+ } catch (e) {
341
+ _failed++;
342
+ _echo(' ${red('✗')} $label');
343
+ rethrow;
344
+ }
345
+ }
346
+ var i = 0;
347
+ final sw = Stopwatch()..start();
348
+ final timer = Timer.periodic(const Duration(milliseconds: 80), (_) {
349
+ i = (i + 1) % _frames.length;
350
+ stdout.write('\r\x1b[K ${cyan(_frames[i])} $label');
351
+ });
352
+ try {
353
+ final r = await task();
354
+ final elapsed = sw.elapsedMilliseconds;
355
+ if (elapsed < 200) {
356
+ await Future.delayed(Duration(milliseconds: 200 - elapsed));
357
+ }
358
+ timer.cancel();
359
+ sw.stop();
360
+ stdout.write('\r\x1b[K ${green('✓')} $label\n');
361
+ _done++;
362
+ return r;
363
+ } catch (e) {
364
+ timer.cancel();
365
+ stdout.write('\r\x1b[K ${red('✗')} $label\n');
366
+ _failed++;
367
+ rethrow;
368
+ }
369
+ }
370
+
371
+ Timer? _activeTimer;
372
+ int _activeIdx = 0;
373
+ String? _activeLabel;
374
+
375
+ /// Print an "active" phase line (⠹ label) that will be replaced in-place
376
+ /// by the next call to [startActive] or finalized by [completeActive].
377
+ /// Use this when a long-running operation reports multiple internal phases
378
+ /// via a callback (e.g. `DeployOptions.onPhase`).
379
+ void startActive(String label) {
380
+ _activeLabel = label;
381
+ if (!_colorOn) {
382
+ _echo(' ${dim('•')} $label');
383
+ return;
384
+ }
385
+ _activeIdx = 0;
386
+ _activeTimer?.cancel();
387
+ _activeTimer = Timer.periodic(const Duration(milliseconds: 80), (_) {
388
+ _activeIdx = (_activeIdx + 1) % _frames.length;
389
+ stdout.write('\r\x1b[K ${cyan(_frames[_activeIdx])} $label');
390
+ });
391
+ }
392
+
393
+ /// Finalize the current active line. If [success] is true (default) the
394
+ /// line becomes `✓ label` and counts toward `_done`. If false, it becomes
395
+ /// `✗ label` and counts toward `_failed`. Call this when the long-running
396
+ /// operation finishes.
397
+ void completeActive({bool success = true}) {
398
+ final label = _activeLabel;
399
+ if (label == null) return;
400
+ _activeTimer?.cancel();
401
+ _activeTimer = null;
402
+ _activeLabel = null;
403
+ if (_colorOn) {
404
+ stdout.write(
405
+ '\r\x1b[K ${success ? green('✓') : red('✗')} $label\n',
406
+ );
407
+ }
408
+ if (success) {
409
+ _done++;
410
+ } else {
411
+ _failed++;
412
+ }
413
+ }
310
414
  }
311
415
 
312
416
  // ── Progress Bar (thin, single-line) ────────────────────────────────────────
@@ -3,7 +3,7 @@ description: >-
3
3
  Command-line interface for flutter_ota_kit (a hot-updater compatible OTA code
4
4
  push tool for Flutter). Deploy bundles, manage channels/rollbacks, run
5
5
  migrations, and inspect the backend — mirroring the `hot-updater` CLI UX.
6
- version: 0.1.0
6
+ version: 0.1.1
7
7
  publish_to: none
8
8
 
9
9
  environment:
@@ -17,13 +17,13 @@ dependencies:
17
17
  collection: ^1.18.0
18
18
  cryptography: ^2.7.0
19
19
  postgres: ^3.4.0
20
- flutter_ota_kit_core: ^0.1.0
21
- flutter_ota_kit_plugin_core: ^0.0.2
22
- flutter_ota_kit_supabase: ^0.1.2
23
- flutter_ota_kit_postgres: ^0.1.1
24
- flutter_ota_kit_cloudflare: ^0.1.1
25
- flutter_ota_kit_aws: ^0.1.1
26
- flutter_ota_kit_pocketbase: ^0.1.0
20
+ flutter_ota_kit_core: ^0.1.6
21
+ flutter_ota_kit_plugin_core: ^0.0.8
22
+ flutter_ota_kit_supabase: ^0.1.8
23
+ flutter_ota_kit_postgres: ^0.1.7
24
+ flutter_ota_kit_cloudflare: ^0.1.7
25
+ flutter_ota_kit_aws: ^0.1.7
26
+ flutter_ota_kit_pocketbase: ^0.1.4
27
27
  http: ^1.2.0
28
28
  shelf: ^1.4.0
29
29
 
@@ -1,6 +1,6 @@
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
- version: 0.1.4
3
+ version: 0.1.6
4
4
  homepage: https://github.com/HYPER12755/flutter-ota-kit
5
5
  repository: https://github.com/HYPER12755/flutter-ota-kit
6
6
  issue_tracker: https://github.com/HYPER12755/flutter-ota-kit/issues
@@ -1,6 +1,6 @@
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
- version: 0.1.5
3
+ version: 0.1.7
4
4
  homepage: https://github.com/HYPER12755/flutter-ota-kit
5
5
  repository: https://github.com/HYPER12755/flutter-ota-kit
6
6
  issue_tracker: https://github.com/HYPER12755/flutter-ota-kit/issues
@@ -11,8 +11,8 @@ environment:
11
11
  sdk: ">=3.13.2 <4.0.0"
12
12
 
13
13
  dependencies:
14
- flutter_ota_kit_core: ^0.1.2
15
- flutter_ota_kit_plugin_core: ^0.0.4
14
+ flutter_ota_kit_core: ^0.1.6
15
+ flutter_ota_kit_plugin_core: ^0.0.8
16
16
  crypto: ^3.0.0
17
17
  http: ^1.2.0
18
18
  path: ^1.9.0
@@ -1,6 +1,6 @@
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
- version: 0.1.5
3
+ version: 0.1.7
4
4
  homepage: https://github.com/HYPER12755/flutter-ota-kit
5
5
  repository: https://github.com/HYPER12755/flutter-ota-kit
6
6
  issue_tracker: https://github.com/HYPER12755/flutter-ota-kit/issues
@@ -11,8 +11,8 @@ environment:
11
11
  sdk: ">=3.13.2 <4.0.0"
12
12
 
13
13
  dependencies:
14
- flutter_ota_kit_core: ^0.1.2
15
- flutter_ota_kit_plugin_core: ^0.0.4
14
+ flutter_ota_kit_core: ^0.1.6
15
+ flutter_ota_kit_plugin_core: ^0.0.8
16
16
  crypto: ^3.0.0
17
17
  http: ^1.2.0
18
18
  path: ^1.9.0
@@ -1,6 +1,6 @@
1
1
  name: flutter_ota_kit_plugin_core
2
2
  description: Plugin core abstractions for flutter_ota_kit — database, storage, and build interfaces.
3
- version: 0.0.6
3
+ version: 0.0.8
4
4
  homepage: https://github.com/HYPER12755/flutter-ota-kit
5
5
  repository: https://github.com/HYPER12755/flutter-ota-kit
6
6
  issue_tracker: https://github.com/HYPER12755/flutter-ota-kit/issues
@@ -11,7 +11,7 @@ environment:
11
11
  sdk: ">=3.13.2 <4.0.0"
12
12
 
13
13
  dependencies:
14
- flutter_ota_kit_core: ^0.1.2
14
+ flutter_ota_kit_core: ^0.1.6
15
15
  mime: ^2.0.0
16
16
 
17
17
  dev_dependencies:
@@ -1,6 +1,6 @@
1
1
  name: flutter_ota_kit_pocketbase
2
2
  description: PocketBase plugin for flutter_ota_kit — local-first self-hostable backend with admin UI, auth, file storage, and realtime.
3
- version: 0.1.2
3
+ version: 0.1.4
4
4
  homepage: https://github.com/HYPER12755/flutter-ota-kit
5
5
  repository: https://github.com/HYPER12755/flutter-ota-kit
6
6
  issue_tracker: https://github.com/HYPER12755/flutter-ota-kit/issues
@@ -11,8 +11,8 @@ environment:
11
11
  sdk: ">=3.13.2 <4.0.0"
12
12
 
13
13
  dependencies:
14
- flutter_ota_kit_core: ^0.1.2
15
- flutter_ota_kit_plugin_core: ^0.0.4
14
+ flutter_ota_kit_core: ^0.1.6
15
+ flutter_ota_kit_plugin_core: ^0.0.8
16
16
  http: ^1.2.0
17
17
 
18
18
  dev_dependencies:
@@ -1,6 +1,6 @@
1
1
  name: flutter_ota_kit_postgres
2
2
  description: Postgres plugin for flutter_ota_kit — database backend.
3
- version: 0.1.5
3
+ version: 0.1.7
4
4
  homepage: https://github.com/HYPER12755/flutter-ota-kit
5
5
  repository: https://github.com/HYPER12755/flutter-ota-kit
6
6
  issue_tracker: https://github.com/HYPER12755/flutter-ota-kit/issues
@@ -11,8 +11,8 @@ environment:
11
11
  sdk: ">=3.13.2 <4.0.0"
12
12
 
13
13
  dependencies:
14
- flutter_ota_kit_core: ^0.1.2
15
- flutter_ota_kit_plugin_core: ^0.0.4
14
+ flutter_ota_kit_core: ^0.1.6
15
+ flutter_ota_kit_plugin_core: ^0.0.8
16
16
  postgres: ^3.4.0
17
17
 
18
18
  dev_dependencies:
@@ -1,6 +1,6 @@
1
1
  name: flutter_ota_kit_supabase
2
2
  description: Supabase plugin for flutter_ota_kit — database + storage backends.
3
- version: 0.1.6
3
+ version: 0.1.8
4
4
  homepage: https://github.com/HYPER12755/flutter-ota-kit
5
5
  repository: https://github.com/HYPER12755/flutter-ota-kit
6
6
  issue_tracker: https://github.com/HYPER12755/flutter-ota-kit/issues
@@ -11,8 +11,8 @@ environment:
11
11
  sdk: ">=3.13.2 <4.0.0"
12
12
 
13
13
  dependencies:
14
- flutter_ota_kit_core: ^0.1.2
15
- flutter_ota_kit_plugin_core: ^0.0.4
14
+ flutter_ota_kit_core: ^0.1.6
15
+ flutter_ota_kit_plugin_core: ^0.0.8
16
16
  http: ^1.2.0
17
17
  supabase: ^2.14.0
18
18
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@_nazmiforreal/flutter-ota",
3
- "version": "0.1.17",
4
- "description": "Command-line interface for flutter_ota_kit an OTA code-push tool for Flutter, hot-updater compatible.",
3
+ "version": "0.1.19",
4
+ "description": "Command-line interface for flutter_ota_kit \u2014 an OTA code-push tool for Flutter, hot-updater compatible.",
5
5
  "bin": {
6
6
  "flutter-ota": "./bin/flutter-ota.js"
7
7
  },
@@ -23,4 +23,4 @@
23
23
  "type": "git",
24
24
  "url": "https://github.com/HYPER12755/flutter-ota-kit"
25
25
  }
26
- }
26
+ }