@_nazmiforreal/flutter-ota 0.1.13 → 0.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/flutter-ota-linux-x64 +0 -0
- package/bin/flutter-ota.js +23 -72
- package/dart-src/packages/cli-tools/.dart_tool/package_config.json +0 -2
- package/dart-src/packages/cli-tools/.dart_tool/package_graph.json +6 -6
- package/dart-src/packages/cli-tools/lib/flutter_ota_kit_cli.dart +2 -2
- package/dart-src/packages/cli-tools/lib/src/commands/build.dart +1 -1
- package/dart-src/packages/cli-tools/lib/src/commands/bundle.dart +112 -124
- package/dart-src/packages/cli-tools/lib/src/commands/channel.dart +20 -28
- package/dart-src/packages/cli-tools/lib/src/commands/config_command.dart +40 -18
- package/dart-src/packages/cli-tools/lib/src/commands/console.dart +10 -11
- package/dart-src/packages/cli-tools/lib/src/commands/deploy.dart +30 -33
- package/dart-src/packages/cli-tools/lib/src/commands/doctor.dart +43 -41
- package/dart-src/packages/cli-tools/lib/src/commands/fingerprint.dart +9 -10
- package/dart-src/packages/cli-tools/lib/src/commands/init.dart +32 -35
- package/dart-src/packages/cli-tools/lib/src/commands/keys.dart +3 -6
- package/dart-src/packages/cli-tools/lib/src/commands/migrate.dart +59 -50
- package/dart-src/packages/cli-tools/lib/src/commands/pocketbase.dart +32 -37
- package/dart-src/packages/cli-tools/lib/src/commands/rollback.dart +13 -16
- package/dart-src/packages/cli-tools/lib/src/commands/storage.dart +12 -20
- package/dart-src/packages/cli-tools/lib/src/config.dart +10 -3
- package/dart-src/packages/cli-tools/lib/src/operations.dart +5 -0
- package/dart-src/packages/cli-tools/lib/src/ui/ui.dart +225 -31
- package/dart-src/packages/cli-tools/lib/src/util.dart +7 -3
- package/dart-src/packages/cli-tools/pubspec.lock +6 -6
- package/dart-src/packages/cli-tools/test/cli_test.dart +6 -0
- package/dart-src/packages/core/CHANGELOG.md +9 -0
- package/dart-src/packages/core/pubspec.yaml +1 -1
- package/dart-src/plugins/aws/CHANGELOG.md +10 -1
- package/dart-src/plugins/aws/pubspec.yaml +3 -3
- package/dart-src/plugins/cloudflare/CHANGELOG.md +9 -1
- package/dart-src/plugins/cloudflare/pubspec.yaml +3 -3
- package/dart-src/plugins/plugin-core/CHANGELOG.md +12 -14
- package/dart-src/plugins/plugin-core/pubspec.yaml +2 -2
- package/dart-src/plugins/pocketbase/pubspec.yaml +2 -2
- package/dart-src/plugins/postgres/CHANGELOG.md +13 -3
- package/dart-src/plugins/postgres/pubspec.yaml +3 -3
- package/dart-src/plugins/supabase/CHANGELOG.md +14 -11
- package/dart-src/plugins/supabase/pubspec.yaml +3 -3
- package/dart-src/plugins/supabase/supabase/migrations/20250103114225_init.sql +7 -3
- package/dart-src/plugins/supabase/supabase/migrations/20250314000000_hot-updater_0.13.0.sql +7 -4
- package/dart-src/plugins/supabase/supabase/migrations/20250516000000_hot-updater_0.18.0.sql +18 -6
- package/dart-src/plugins/supabase/supabase/migrations/20251014000000_hot-updater_0.21.0.sql +4 -2
- package/dart-src/plugins/supabase/supabase/migrations/20260401000000_hot-updater_0.29.0.sql +4 -2
- package/dart-src/plugins/supabase/supabase/migrations/20260520014100_hot-updater_rls.sql +22 -6
- package/migrations/supabase/20250103114225_init.sql +7 -3
- package/migrations/supabase/20250314000000_hot-updater_0.13.0.sql +7 -4
- package/migrations/supabase/20250516000000_hot-updater_0.18.0.sql +18 -6
- package/migrations/supabase/20251014000000_hot-updater_0.21.0.sql +4 -2
- package/migrations/supabase/20260401000000_hot-updater_0.29.0.sql +4 -2
- package/migrations/supabase/20260520014100_hot-updater_rls.sql +22 -6
- package/package.json +1 -1
- package/scripts/vendor.sh +32 -0
- package/migrations/aws/README.md +0 -7
- package/migrations/cloudflare/bundles.sql +0 -42
|
@@ -4,12 +4,15 @@ import 'dart:async';
|
|
|
4
4
|
import 'dart:io';
|
|
5
5
|
import 'dart:math' as math;
|
|
6
6
|
|
|
7
|
-
/// Terminal UI toolkit for the
|
|
8
|
-
/// bordered boxes, step logs, dynamic spinners and progress bars.
|
|
7
|
+
/// Terminal UI toolkit for the flutter-ota CLI.
|
|
9
8
|
///
|
|
10
|
-
///
|
|
11
|
-
///
|
|
12
|
-
///
|
|
9
|
+
/// Provides colored text, banners, bordered boxes, step logs, spinners,
|
|
10
|
+
/// thin progress bars, and column-aligned tables.
|
|
11
|
+
///
|
|
12
|
+
/// Everything degrades gracefully to plain text when stdout is not a TTY
|
|
13
|
+
/// or the `NO_COLOR` env var is set.
|
|
14
|
+
|
|
15
|
+
// ── ANSI codes ───────────────────────────────────────────────────────────────
|
|
13
16
|
|
|
14
17
|
const _kReset = '\x1b[0m';
|
|
15
18
|
const _kRed = '\x1b[31m';
|
|
@@ -23,6 +26,8 @@ const _kBold = '\x1b[1m';
|
|
|
23
26
|
|
|
24
27
|
const List<String> _frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
25
28
|
|
|
29
|
+
// ── TTY detection ────────────────────────────────────────────────────────────
|
|
30
|
+
|
|
26
31
|
bool get _noColor {
|
|
27
32
|
final v = Platform.environment['NO_COLOR'];
|
|
28
33
|
return v != null && v.isNotEmpty;
|
|
@@ -31,6 +36,8 @@ bool get _noColor {
|
|
|
31
36
|
bool get _colorOn =>
|
|
32
37
|
!_noColor && stdout.hasTerminal && stdout.supportsAnsiEscapes;
|
|
33
38
|
|
|
39
|
+
// ── Color helpers ────────────────────────────────────────────────────────────
|
|
40
|
+
|
|
34
41
|
String _c(String code, String s) => _colorOn ? '$code$s$_kReset' : s;
|
|
35
42
|
|
|
36
43
|
String red(String s) => _c(_kRed, s);
|
|
@@ -43,7 +50,19 @@ String gray(String s) => _c(_kGray, s);
|
|
|
43
50
|
String dim(String s) => _c(_kGray, s);
|
|
44
51
|
String bold(String s) => _c(_kBold, s);
|
|
45
52
|
|
|
46
|
-
|
|
53
|
+
// ── Terminal width ───────────────────────────────────────────────────────────
|
|
54
|
+
|
|
55
|
+
int get _cols {
|
|
56
|
+
if (stdout.hasTerminal) return stdout.terminalColumns;
|
|
57
|
+
final envCols = Platform.environment['COLUMNS'];
|
|
58
|
+
if (envCols != null) {
|
|
59
|
+
final parsed = int.tryParse(envCols);
|
|
60
|
+
if (parsed != null && parsed > 0) return parsed;
|
|
61
|
+
}
|
|
62
|
+
return 80;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// ── Visible width (ANSI-aware) ──────────────────────────────────────────────
|
|
47
66
|
|
|
48
67
|
final _ansi = RegExp('\x1b\\[[0-9;]*m');
|
|
49
68
|
|
|
@@ -51,26 +70,38 @@ int _dispWidth(String s) => s.replaceAll(_ansi, '').length;
|
|
|
51
70
|
|
|
52
71
|
void _echo(String s) => stdout.writeln(s);
|
|
53
72
|
|
|
73
|
+
// ── Key-value pair ───────────────────────────────────────────────────────────
|
|
74
|
+
|
|
54
75
|
/// `key value` laid out in a fixed 18-char column (visible-width aware).
|
|
76
|
+
/// Long values are truncated with `…` to prevent box overflow.
|
|
55
77
|
String kv(String k, String v) {
|
|
56
78
|
final pad = math.max(0, 18 - _dispWidth(k));
|
|
57
|
-
|
|
79
|
+
final maxVal = math.max(0, _cols - 24 - _dispWidth(k));
|
|
80
|
+
final display = maxVal > 0 && _dispWidth(v) > maxVal
|
|
81
|
+
? '${_cut(v, maxVal - 1)}…'
|
|
82
|
+
: v;
|
|
83
|
+
return '${dim(k)}${' ' * pad} $display';
|
|
58
84
|
}
|
|
59
85
|
|
|
86
|
+
// ── Banner ───────────────────────────────────────────────────────────────────
|
|
87
|
+
|
|
60
88
|
void banner(String name) {
|
|
61
89
|
_echo('');
|
|
62
90
|
_echo(
|
|
63
|
-
' ${cyan('▶')} ${cyan(bold('
|
|
91
|
+
' ${cyan('▶')} ${cyan(bold('flutter-ota'))} ${dim('·')} ${bold(name)}',
|
|
64
92
|
);
|
|
65
|
-
|
|
93
|
+
final sepLen = math.max(20, math.min(_cols - 4, 72));
|
|
94
|
+
_echo(' ${dim('─' * sepLen)}');
|
|
66
95
|
}
|
|
67
96
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
void warn(String msg) => _echo(' ${yellow('!')} ${yellow(msg)}');
|
|
97
|
+
// ── Single-line status ──────────────────────────────────────────────────────
|
|
71
98
|
|
|
99
|
+
void step(String msg) => _echo(' ${green('✓')} $msg');
|
|
100
|
+
void warn(String msg) => _echo(' ${yellow('⚠')} ${yellow(msg)}');
|
|
72
101
|
void err(String msg) => _echo(' ${red('✗')} ${red(msg)}');
|
|
73
102
|
|
|
103
|
+
// ── Spinner ──────────────────────────────────────────────────────────────────
|
|
104
|
+
|
|
74
105
|
/// Run [task] while showing a live spinner; replaces the line with a
|
|
75
106
|
/// `${green('✓')} done` summary when finished (or `✗` on error).
|
|
76
107
|
Future<T> spinner<T>(
|
|
@@ -101,6 +132,8 @@ Future<T> spinner<T>(
|
|
|
101
132
|
}
|
|
102
133
|
}
|
|
103
134
|
|
|
135
|
+
// ── Word wrap ────────────────────────────────────────────────────────────────
|
|
136
|
+
|
|
104
137
|
List<String> _wrap(String text, int inner) {
|
|
105
138
|
if (text.isEmpty) return [''];
|
|
106
139
|
final result = <String>[];
|
|
@@ -148,6 +181,11 @@ String _cut(String s, int inner) {
|
|
|
148
181
|
String _splitLong(String word, int inner, List<String> out) {
|
|
149
182
|
var rem = word;
|
|
150
183
|
while (_dispWidth(rem) > inner) {
|
|
184
|
+
if (_dispWidth(rem) <= inner + 2) {
|
|
185
|
+
// Truncate with … instead of hard-breaking mid-word.
|
|
186
|
+
out.add('${_cut(rem, inner - 1)}…');
|
|
187
|
+
return '';
|
|
188
|
+
}
|
|
151
189
|
final cut = _cut(rem, inner);
|
|
152
190
|
out.add(cut);
|
|
153
191
|
rem = rem.substring(cut.length);
|
|
@@ -155,14 +193,19 @@ String _splitLong(String word, int inner, List<String> out) {
|
|
|
155
193
|
return rem;
|
|
156
194
|
}
|
|
157
195
|
|
|
196
|
+
// ── Box ──────────────────────────────────────────────────────────────────────
|
|
197
|
+
|
|
198
|
+
/// Mathematically precise box width: single formula for both title and content.
|
|
158
199
|
int _boxWidth(List<String> lines, String title) {
|
|
159
|
-
var longest =
|
|
200
|
+
var longest = 0;
|
|
160
201
|
for (final l in lines) {
|
|
161
202
|
for (final w in l.split('\n')) {
|
|
162
203
|
longest = math.max(longest, _dispWidth(w));
|
|
163
204
|
}
|
|
164
205
|
}
|
|
165
|
-
final
|
|
206
|
+
final titleNeeded = _dispWidth(title) + 4;
|
|
207
|
+
final contentNeeded = longest + 4;
|
|
208
|
+
final target = math.max(titleNeeded, math.max(contentNeeded, 40));
|
|
166
209
|
return math.max(math.min(_cols - 1, target), 20);
|
|
167
210
|
}
|
|
168
211
|
|
|
@@ -171,18 +214,25 @@ int _boxWidth(List<String> lines, String title) {
|
|
|
171
214
|
void box(String title, List<String> lines) {
|
|
172
215
|
final width = _boxWidth(lines, title);
|
|
173
216
|
final inner = width - 4;
|
|
217
|
+
|
|
218
|
+
// Wrap content to fit inner width.
|
|
174
219
|
final wrapped = <String>[];
|
|
175
220
|
for (final l in lines) {
|
|
176
|
-
|
|
221
|
+
if (l.isEmpty) {
|
|
222
|
+
wrapped.add('');
|
|
223
|
+
} else {
|
|
224
|
+
wrapped.addAll(_wrap(l, inner));
|
|
225
|
+
}
|
|
177
226
|
}
|
|
178
227
|
|
|
228
|
+
// Title centered in top border.
|
|
179
229
|
final titleText = ' $title ';
|
|
180
230
|
final tVisible = _dispWidth(titleText);
|
|
181
|
-
|
|
182
|
-
final
|
|
183
|
-
final
|
|
184
|
-
|
|
185
|
-
_echo(
|
|
231
|
+
final totalDashes = width - 2 - tVisible;
|
|
232
|
+
final leftDashes = math.max(1, totalDashes ~/ 2);
|
|
233
|
+
final rightDashes = totalDashes - leftDashes;
|
|
234
|
+
|
|
235
|
+
_echo('╭${'─' * leftDashes}$titleText${'─' * rightDashes}╮');
|
|
186
236
|
for (final l in wrapped) {
|
|
187
237
|
final pad = math.max(0, inner - _dispWidth(l));
|
|
188
238
|
_echo('│ $l${' ' * pad} │');
|
|
@@ -190,44 +240,188 @@ void box(String title, List<String> lines) {
|
|
|
190
240
|
_echo('╰${'─' * (width - 2)}╯');
|
|
191
241
|
}
|
|
192
242
|
|
|
193
|
-
|
|
194
|
-
|
|
243
|
+
// ── Steps ────────────────────────────────────────────────────────────────────
|
|
244
|
+
|
|
245
|
+
/// Multi-step progress tracker with uv-style clean output.
|
|
246
|
+
///
|
|
247
|
+
/// Each step prints a single line: `✓ label` (done), `✗ label` (failed),
|
|
248
|
+
/// or `· label` (skipped). After all steps, call [summary] to print a
|
|
249
|
+
/// boxed summary with counts and elapsed time.
|
|
250
|
+
///
|
|
251
|
+
/// Example:
|
|
252
|
+
/// ```dart
|
|
253
|
+
/// final s = Steps('migrate · supabase');
|
|
254
|
+
/// s.success('Applied 20250103_init.sql');
|
|
255
|
+
/// s.skip('Skipped 20251014_0.21.0.sql');
|
|
256
|
+
/// s.summary(); // prints "2 applied · 1 skipped · 0 errors · 245ms"
|
|
257
|
+
/// ```
|
|
258
|
+
class Steps {
|
|
259
|
+
Steps(this.title) : _sw = Stopwatch()..start();
|
|
260
|
+
|
|
261
|
+
final String title;
|
|
262
|
+
final Stopwatch _sw;
|
|
263
|
+
int _done = 0;
|
|
264
|
+
int _failed = 0;
|
|
265
|
+
int _skipped = 0;
|
|
266
|
+
|
|
267
|
+
/// Whether any step has failed.
|
|
268
|
+
bool get hasErrors => _failed > 0;
|
|
269
|
+
|
|
270
|
+
/// Step completed successfully.
|
|
271
|
+
void success(String label) {
|
|
272
|
+
_done++;
|
|
273
|
+
_echo(' ${green('✓')} $label');
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/// Step failed.
|
|
277
|
+
void fail(String label) {
|
|
278
|
+
_failed++;
|
|
279
|
+
_echo(' ${red('✗')} $label');
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/// Step skipped (e.g. already applied).
|
|
283
|
+
void skip(String label) {
|
|
284
|
+
_skipped++;
|
|
285
|
+
_echo(' ${dim('·')} $label');
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/// Print boxed summary: "N applied · N skipped · N errors · TIME"
|
|
289
|
+
void summary() {
|
|
290
|
+
_sw.stop();
|
|
291
|
+
final ms = _sw.elapsedMilliseconds;
|
|
292
|
+
final time = ms >= 1000
|
|
293
|
+
? '${(ms / 1000).toStringAsFixed(1)}s'
|
|
294
|
+
: '${ms}ms';
|
|
295
|
+
final parts = <String>[];
|
|
296
|
+
if (_done > 0) parts.add('${_done} completed');
|
|
297
|
+
if (_skipped > 0) parts.add('${_skipped} skipped');
|
|
298
|
+
if (_failed > 0) parts.add('${red('${_failed} error${_failed > 1 ? 's' : ''}')}');
|
|
299
|
+
if (parts.isEmpty) parts.add('no steps');
|
|
300
|
+
parts.add(time);
|
|
301
|
+
box('summary', [parts.join(' · ')]);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// ── Progress Bar (thin, single-line) ────────────────────────────────────────
|
|
306
|
+
|
|
307
|
+
/// Thin single-line progress bar with spinner, label, bar, percent, and time.
|
|
308
|
+
///
|
|
309
|
+
/// Renders as: `⠹ Label ████░░░░ 50% 1.3s`
|
|
310
|
+
/// On finish: `✓ Label in 1.3s`
|
|
195
311
|
class ProgressBar {
|
|
196
312
|
ProgressBar(this.total, this.label);
|
|
197
313
|
|
|
198
314
|
int total;
|
|
199
|
-
|
|
315
|
+
String label;
|
|
200
316
|
int _current = 0;
|
|
201
317
|
int _spin = 0;
|
|
202
318
|
bool _closed = false;
|
|
319
|
+
final Stopwatch _sw = Stopwatch()..start();
|
|
320
|
+
late String _label = label;
|
|
203
321
|
|
|
204
|
-
void update(int current, [String?
|
|
322
|
+
void update(int current, [String? newLabel]) {
|
|
205
323
|
_current = current;
|
|
206
|
-
if (
|
|
324
|
+
if (newLabel != null) _label = newLabel;
|
|
207
325
|
_draw();
|
|
208
326
|
if (total > 0 && _current >= total) _finish();
|
|
209
327
|
}
|
|
210
328
|
|
|
211
|
-
late String _label = label;
|
|
212
|
-
|
|
213
329
|
void _draw() {
|
|
214
330
|
if (_closed) return;
|
|
215
331
|
if (!_colorOn) {
|
|
216
332
|
_echo(' $_label: $_current/$total');
|
|
217
333
|
return;
|
|
218
334
|
}
|
|
219
|
-
|
|
335
|
+
|
|
220
336
|
final pct = total > 0 ? (_current / total).clamp(0.0, 1.0) : 1.0;
|
|
337
|
+
|
|
338
|
+
// Thin bar: width scales to terminal, max 20 chars.
|
|
339
|
+
final barW = math.min(20, math.max(8, _cols - 40));
|
|
221
340
|
final filled = (barW * pct).round();
|
|
222
|
-
final
|
|
341
|
+
final empty = barW - filled;
|
|
342
|
+
final bar = '${yellow('█' * filled)}${gray('░' * empty)}';
|
|
343
|
+
|
|
223
344
|
_spin = (_spin + 1) % _frames.length;
|
|
224
345
|
final pctStr = '${(pct * 100).round()}%'.padLeft(4);
|
|
225
|
-
|
|
346
|
+
|
|
347
|
+
stdout.write(
|
|
348
|
+
'\r\x1b[K ${cyan(_frames[_spin])} $_label $bar $pctStr',
|
|
349
|
+
);
|
|
226
350
|
}
|
|
227
351
|
|
|
228
352
|
void _finish() {
|
|
229
353
|
if (_closed) return;
|
|
230
354
|
_closed = true;
|
|
231
|
-
|
|
355
|
+
_sw.stop();
|
|
356
|
+
final ms = _sw.elapsedMilliseconds;
|
|
357
|
+
final time = ms >= 1000
|
|
358
|
+
? '${(ms / 1000).toStringAsFixed(1)}s'
|
|
359
|
+
: '${ms}ms';
|
|
360
|
+
if (_colorOn) {
|
|
361
|
+
stdout.write('\r\x1b[K ${green('✓')} $_label in $time\n');
|
|
362
|
+
} else {
|
|
363
|
+
_echo(' ✓ $_label in $time');
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/// Force finish (for when total is not reached).
|
|
368
|
+
void close() {
|
|
369
|
+
if (!_closed) _finish();
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// ── Table ────────────────────────────────────────────────────────────────────
|
|
374
|
+
|
|
375
|
+
/// Column-aligned table inside a bordered box.
|
|
376
|
+
///
|
|
377
|
+
/// Example:
|
|
378
|
+
/// ```dart
|
|
379
|
+
/// table('3 bundles', ['#', 'ID', 'CHANNEL', 'ON'], [
|
|
380
|
+
/// ['0', 'abc-123', 'production', '✓'],
|
|
381
|
+
/// ['1', 'def-456', 'staging', '✗'],
|
|
382
|
+
/// ]);
|
|
383
|
+
/// ```
|
|
384
|
+
void table(String title, List<String> headers, List<List<String>> rows) {
|
|
385
|
+
if (headers.isEmpty) return;
|
|
386
|
+
|
|
387
|
+
// Calculate column widths from content.
|
|
388
|
+
final colCount = headers.length;
|
|
389
|
+
final colWidths = List<int>.filled(colCount, 0);
|
|
390
|
+
for (var i = 0; i < colCount; i++) {
|
|
391
|
+
colWidths[i] = _dispWidth(headers[i]);
|
|
392
|
+
}
|
|
393
|
+
for (final row in rows) {
|
|
394
|
+
for (var i = 0; i < colCount && i < row.length; i++) {
|
|
395
|
+
colWidths[i] = math.max(colWidths[i], _dispWidth(row[i]));
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// Build formatted lines.
|
|
400
|
+
final formatted = <String>[];
|
|
401
|
+
|
|
402
|
+
// Header line.
|
|
403
|
+
final headerParts = <String>[];
|
|
404
|
+
for (var i = 0; i < colCount; i++) {
|
|
405
|
+
headerParts.add(headers[i].padRight(colWidths[i]));
|
|
406
|
+
}
|
|
407
|
+
formatted.add(bold(headerParts.join(' ')));
|
|
408
|
+
|
|
409
|
+
// Separator line.
|
|
410
|
+
final sepParts = <String>[];
|
|
411
|
+
for (var i = 0; i < colCount; i++) {
|
|
412
|
+
sepParts.add('─' * colWidths[i]);
|
|
232
413
|
}
|
|
414
|
+
formatted.add(dim(sepParts.join(' ')));
|
|
415
|
+
|
|
416
|
+
// Data rows.
|
|
417
|
+
for (final row in rows) {
|
|
418
|
+
final parts = <String>[];
|
|
419
|
+
for (var i = 0; i < colCount; i++) {
|
|
420
|
+
final cell = i < row.length ? row[i] : '';
|
|
421
|
+
parts.add(cell.padRight(colWidths[i]));
|
|
422
|
+
}
|
|
423
|
+
formatted.add(parts.join(' '));
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
box(title, formatted);
|
|
233
427
|
}
|
|
@@ -51,9 +51,13 @@ String generateFingerprint(String directory) {
|
|
|
51
51
|
for (final entity in dir.listSync(recursive: true)) {
|
|
52
52
|
if (entity is! File) continue;
|
|
53
53
|
final relative = p.relative(entity.path, from: dir.path);
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
try {
|
|
55
|
+
final content = File(entity.path).readAsBytesSync();
|
|
56
|
+
final hash = sha256Hex(content);
|
|
57
|
+
entries.add('$relative:$hash');
|
|
58
|
+
} on FileSystemException {
|
|
59
|
+
// Skip unreadable files (sockets, pipes, broken symlinks).
|
|
60
|
+
}
|
|
57
61
|
}
|
|
58
62
|
entries.sort();
|
|
59
63
|
return sha256Hex(utf8.encode(entries.join('\n')));
|
|
@@ -159,28 +159,28 @@ packages:
|
|
|
159
159
|
path: "../../plugins/aws"
|
|
160
160
|
relative: true
|
|
161
161
|
source: path
|
|
162
|
-
version: "0.1.
|
|
162
|
+
version: "0.1.3"
|
|
163
163
|
flutter_ota_kit_cloudflare:
|
|
164
164
|
dependency: "direct main"
|
|
165
165
|
description:
|
|
166
166
|
path: "../../plugins/cloudflare"
|
|
167
167
|
relative: true
|
|
168
168
|
source: path
|
|
169
|
-
version: "0.1.
|
|
169
|
+
version: "0.1.3"
|
|
170
170
|
flutter_ota_kit_core:
|
|
171
171
|
dependency: "direct main"
|
|
172
172
|
description:
|
|
173
173
|
path: "../core"
|
|
174
174
|
relative: true
|
|
175
175
|
source: path
|
|
176
|
-
version: "0.1.
|
|
176
|
+
version: "0.1.2"
|
|
177
177
|
flutter_ota_kit_plugin_core:
|
|
178
178
|
dependency: "direct main"
|
|
179
179
|
description:
|
|
180
180
|
path: "../../plugins/plugin-core"
|
|
181
181
|
relative: true
|
|
182
182
|
source: path
|
|
183
|
-
version: "0.0.
|
|
183
|
+
version: "0.0.4"
|
|
184
184
|
flutter_ota_kit_pocketbase:
|
|
185
185
|
dependency: "direct main"
|
|
186
186
|
description:
|
|
@@ -194,14 +194,14 @@ packages:
|
|
|
194
194
|
path: "../../plugins/postgres"
|
|
195
195
|
relative: true
|
|
196
196
|
source: path
|
|
197
|
-
version: "0.1.
|
|
197
|
+
version: "0.1.3"
|
|
198
198
|
flutter_ota_kit_supabase:
|
|
199
199
|
dependency: "direct main"
|
|
200
200
|
description:
|
|
201
201
|
path: "../../plugins/supabase"
|
|
202
202
|
relative: true
|
|
203
203
|
source: path
|
|
204
|
-
version: "0.1.
|
|
204
|
+
version: "0.1.4"
|
|
205
205
|
frontend_server_client:
|
|
206
206
|
dependency: transitive
|
|
207
207
|
description:
|
|
@@ -381,6 +381,7 @@ void main() {
|
|
|
381
381
|
source: dir.path,
|
|
382
382
|
channel: 'production',
|
|
383
383
|
platform: 'android',
|
|
384
|
+
targetAppVersion: '1.0.0',
|
|
384
385
|
),
|
|
385
386
|
);
|
|
386
387
|
expect(bundle.enabled, isTrue);
|
|
@@ -402,6 +403,7 @@ void main() {
|
|
|
402
403
|
source: dir.path,
|
|
403
404
|
channel: 'production',
|
|
404
405
|
platform: 'android',
|
|
406
|
+
targetAppVersion: '1.0.0',
|
|
405
407
|
),
|
|
406
408
|
);
|
|
407
409
|
final res = await listBundles(
|
|
@@ -429,6 +431,7 @@ void main() {
|
|
|
429
431
|
source: dir.path,
|
|
430
432
|
channel: 'production',
|
|
431
433
|
platform: 'android',
|
|
434
|
+
targetAppVersion: '1.0.0',
|
|
432
435
|
),
|
|
433
436
|
);
|
|
434
437
|
await deleteBundle(backend, deployed.id);
|
|
@@ -448,6 +451,7 @@ void main() {
|
|
|
448
451
|
source: dir.path,
|
|
449
452
|
channel: 'production',
|
|
450
453
|
platform: 'android',
|
|
454
|
+
targetAppVersion: '1.0.0',
|
|
451
455
|
),
|
|
452
456
|
);
|
|
453
457
|
final second = await deployBundle(
|
|
@@ -456,6 +460,7 @@ void main() {
|
|
|
456
460
|
source: dir.path,
|
|
457
461
|
channel: 'production',
|
|
458
462
|
platform: 'android',
|
|
463
|
+
targetAppVersion: '2.0.0',
|
|
459
464
|
),
|
|
460
465
|
);
|
|
461
466
|
final disabled = await rollbackChannel(backend, 'production');
|
|
@@ -477,6 +482,7 @@ void main() {
|
|
|
477
482
|
source: dir.path,
|
|
478
483
|
channel: 'production',
|
|
479
484
|
platform: 'android',
|
|
485
|
+
targetAppVersion: '1.0.0',
|
|
480
486
|
),
|
|
481
487
|
);
|
|
482
488
|
await promoteBundle(backend, b.id, 'staging');
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
## 0.1.2
|
|
2
|
+
|
|
3
|
+
- Add dartdoc on internal API surfaces (10/10 pana dartdoc coverage).
|
|
4
|
+
|
|
5
|
+
## 0.1.1
|
|
6
|
+
|
|
7
|
+
- Fix `<id>` angle bracket in dartdoc (`bundle.dart:23`) being interpreted as HTML by Markdown renderers.
|
|
8
|
+
- Repository moved to `https://github.com/HYPER12755/flutter-ota-kit`.
|
|
9
|
+
|
|
1
10
|
## 0.1.0
|
|
2
11
|
|
|
3
12
|
- Initial release of `flutter_ota_kit_core` as part of the flutter_ota_kit OTA toolkit.
|
|
@@ -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.
|
|
3
|
+
version: 0.1.2
|
|
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,9 +1,18 @@
|
|
|
1
|
-
## 0.1.
|
|
1
|
+
## 0.1.3
|
|
2
|
+
|
|
3
|
+
- Add dartdoc on internal API surfaces (10/10 pana dartdoc coverage).
|
|
4
|
+
|
|
5
|
+
## 0.1.2
|
|
2
6
|
|
|
7
|
+
- Bump `pointycastle` to `^4.0.0` (API-compatible, security update).
|
|
3
8
|
- Add `withCloudFrontSignedUrl` helper for time-limited download URLs.
|
|
4
9
|
- Add `defaultAwsCloudFrontClientFactory` export.
|
|
5
10
|
- Repository moved to `https://github.com/HYPER12755/flutter-ota-kit`.
|
|
6
11
|
|
|
12
|
+
## 0.1.1
|
|
13
|
+
|
|
14
|
+
- Initial test release of the AWS S3 + CloudFront storage plugin.
|
|
15
|
+
|
|
7
16
|
## 0.1.0
|
|
8
17
|
|
|
9
18
|
- Initial release of `flutter_ota_kit_aws` as part of the flutter_ota_kit OTA toolkit.
|
|
@@ -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.
|
|
3
|
+
version: 0.1.3
|
|
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.
|
|
15
|
-
flutter_ota_kit_plugin_core: ^0.0.
|
|
14
|
+
flutter_ota_kit_core: ^0.1.2
|
|
15
|
+
flutter_ota_kit_plugin_core: ^0.0.4
|
|
16
16
|
crypto: ^3.0.0
|
|
17
17
|
http: ^1.2.0
|
|
18
18
|
path: ^1.9.0
|
|
@@ -1,10 +1,18 @@
|
|
|
1
|
-
## 0.1.
|
|
1
|
+
## 0.1.3
|
|
2
|
+
|
|
3
|
+
- Add dartdoc on internal API surfaces (10/10 pana dartdoc coverage).
|
|
4
|
+
|
|
5
|
+
## 0.1.2
|
|
2
6
|
|
|
3
7
|
- Add `parseMetadata` / `parseTargetCohorts` exports from the D1 bundle
|
|
4
8
|
mapper for writing custom Cloudflare Worker logic.
|
|
5
9
|
- Add `defaultRolloutCohortCount` export.
|
|
6
10
|
- Repository moved to `https://github.com/HYPER12755/flutter-ota-kit`.
|
|
7
11
|
|
|
12
|
+
## 0.1.1
|
|
13
|
+
|
|
14
|
+
- Initial test release of the Cloudflare D1 + R2 storage plugin.
|
|
15
|
+
|
|
8
16
|
## 0.1.0
|
|
9
17
|
|
|
10
18
|
- Initial release of `flutter_ota_kit_cloudflare` as part of the flutter_ota_kit OTA toolkit.
|
|
@@ -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.
|
|
3
|
+
version: 0.1.3
|
|
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.
|
|
15
|
-
flutter_ota_kit_plugin_core: ^0.0.
|
|
14
|
+
flutter_ota_kit_core: ^0.1.2
|
|
15
|
+
flutter_ota_kit_plugin_core: ^0.0.4
|
|
16
16
|
crypto: ^3.0.0
|
|
17
17
|
http: ^1.2.0
|
|
18
18
|
path: ^1.9.0
|
|
@@ -1,19 +1,17 @@
|
|
|
1
|
-
## 0.0.
|
|
1
|
+
## 0.0.4
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
- Add dartdoc on internal API surfaces (10/10 pana dartdoc coverage).
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
`ensureExpectedBucket` (the S3/R2 bucket-mismatch guard, formerly copied
|
|
7
|
-
byte-for-byte in the cloudflare + aws storage profiles), `normalizeMetadata`
|
|
8
|
-
(bundle `metadata` JSON-string/object normalization, formerly in the supabase +
|
|
9
|
-
postgres mappers and cloudflare's `parseMetadata`), `buildBundlePatchId`
|
|
10
|
-
(the `${bundleId}:${baseBundleId}` patch primary key, formerly in three mappers),
|
|
11
|
-
and `updateJsonKeyRegex` (the `update.json` key matcher, formerly duplicated in
|
|
12
|
-
the aws blob database + `createBlobDatabasePlugin`). The four backend plugins
|
|
13
|
-
now import these from `plugin-core` instead of maintaining their own copies.
|
|
14
|
-
Public API of the backend packages is unchanged (cloudflare still re-exports
|
|
15
|
-
`buildBundlePatchId` / `parseMetadata` as aliases of the shared helpers).
|
|
5
|
+
## 0.0.3
|
|
16
6
|
|
|
17
|
-
|
|
7
|
+
- Bump `mime` constraint to `^2.0.0` (now used for asset content-type detection).
|
|
8
|
+
- Add `parseStorageUri` + `ParsedStorageUri` exports for the storage URI helpers.
|
|
9
|
+
- Repository moved to `https://github.com/HYPER12755/flutter-ota-kit`.
|
|
10
|
+
|
|
11
|
+
## 0.0.2
|
|
18
12
|
|
|
19
13
|
- Initial release of `flutter_ota_kit_plugin_core` as part of the flutter_ota_kit OTA toolkit.
|
|
14
|
+
|
|
15
|
+
## 0.0.1
|
|
16
|
+
|
|
17
|
+
- Pre-release of the plugin core abstractions.
|
|
@@ -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.
|
|
3
|
+
version: 0.0.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,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.
|
|
14
|
+
flutter_ota_kit_core: ^0.1.2
|
|
15
15
|
mime: ^2.0.0
|
|
16
16
|
|
|
17
17
|
dev_dependencies:
|