@_nazmiforreal/flutter-ota 0.1.16 → 0.1.17
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/dart-src/packages/cli-tools/.dart_tool/package_graph.json +7 -7
- package/dart-src/packages/cli-tools/lib/flutter_ota_kit_cli.dart +200 -0
- package/dart-src/packages/cli-tools/lib/src/commands/bundle.dart +0 -21
- package/dart-src/packages/cli-tools/lib/src/commands/channel.dart +0 -10
- package/dart-src/packages/cli-tools/lib/src/commands/config_command.dart +2 -12
- package/dart-src/packages/cli-tools/lib/src/commands/console.dart +3 -1
- package/dart-src/packages/cli-tools/lib/src/commands/deploy.dart +1 -5
- package/dart-src/packages/cli-tools/lib/src/commands/fingerprint.dart +3 -4
- package/dart-src/packages/cli-tools/lib/src/commands/init.dart +19 -47
- package/dart-src/packages/cli-tools/lib/src/commands/keys.dart +1 -6
- package/dart-src/packages/cli-tools/lib/src/commands/pocketbase.dart +2 -0
- package/dart-src/packages/cli-tools/lib/src/pocketbase/installer.dart +0 -1
- package/dart-src/packages/cli-tools/lib/src/pocketbase/schema_installer.dart +0 -3
- package/dart-src/packages/cli-tools/lib/src/runner.dart +15 -1
- package/dart-src/packages/cli-tools/lib/src/ui/ui.dart +21 -7
- package/dart-src/packages/cli-tools/pubspec.lock +7 -7
- package/dart-src/packages/core/CHANGELOG.md +1 -12
- package/dart-src/packages/core/LICENSE +1 -1
- package/dart-src/packages/core/pubspec.yaml +1 -1
- package/dart-src/plugins/aws/CHANGELOG.md +1 -18
- package/dart-src/plugins/aws/LICENSE +1 -1
- package/dart-src/plugins/aws/pubspec.yaml +1 -1
- package/dart-src/plugins/cloudflare/CHANGELOG.md +1 -18
- package/dart-src/plugins/cloudflare/LICENSE +1 -1
- package/dart-src/plugins/cloudflare/pubspec.yaml +1 -1
- package/dart-src/plugins/plugin-core/CHANGELOG.md +1 -17
- package/dart-src/plugins/plugin-core/LICENSE +1 -1
- package/dart-src/plugins/plugin-core/pubspec.yaml +1 -1
- package/dart-src/plugins/pocketbase/CHANGELOG.md +1 -8
- package/dart-src/plugins/pocketbase/LICENSE +1 -1
- package/dart-src/plugins/pocketbase/pubspec.yaml +1 -1
- package/dart-src/plugins/postgres/CHANGELOG.md +1 -19
- package/dart-src/plugins/postgres/LICENSE +1 -1
- package/dart-src/plugins/postgres/pubspec.yaml +1 -1
- package/dart-src/plugins/supabase/CHANGELOG.md +1 -23
- package/dart-src/plugins/supabase/LICENSE +1 -1
- package/dart-src/plugins/supabase/pubspec.yaml +1 -1
- package/package.json +1 -1
- package/scripts/vendor.sh +0 -0
|
Binary file
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
},
|
|
31
31
|
{
|
|
32
32
|
"name": "flutter_ota_kit_pocketbase",
|
|
33
|
-
"version": "0.1.
|
|
33
|
+
"version": "0.1.2",
|
|
34
34
|
"dependencies": [
|
|
35
35
|
"flutter_ota_kit_core",
|
|
36
36
|
"flutter_ota_kit_plugin_core",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
},
|
|
40
40
|
{
|
|
41
41
|
"name": "flutter_ota_kit_aws",
|
|
42
|
-
"version": "0.1.
|
|
42
|
+
"version": "0.1.5",
|
|
43
43
|
"dependencies": [
|
|
44
44
|
"asn1lib",
|
|
45
45
|
"crypto",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
},
|
|
53
53
|
{
|
|
54
54
|
"name": "flutter_ota_kit_cloudflare",
|
|
55
|
-
"version": "0.1.
|
|
55
|
+
"version": "0.1.5",
|
|
56
56
|
"dependencies": [
|
|
57
57
|
"crypto",
|
|
58
58
|
"flutter_ota_kit_core",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
},
|
|
64
64
|
{
|
|
65
65
|
"name": "flutter_ota_kit_postgres",
|
|
66
|
-
"version": "0.1.
|
|
66
|
+
"version": "0.1.5",
|
|
67
67
|
"dependencies": [
|
|
68
68
|
"flutter_ota_kit_core",
|
|
69
69
|
"flutter_ota_kit_plugin_core",
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
},
|
|
73
73
|
{
|
|
74
74
|
"name": "flutter_ota_kit_supabase",
|
|
75
|
-
"version": "0.1.
|
|
75
|
+
"version": "0.1.6",
|
|
76
76
|
"dependencies": [
|
|
77
77
|
"flutter_ota_kit_core",
|
|
78
78
|
"flutter_ota_kit_plugin_core",
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
},
|
|
83
83
|
{
|
|
84
84
|
"name": "flutter_ota_kit_plugin_core",
|
|
85
|
-
"version": "0.0.
|
|
85
|
+
"version": "0.0.6",
|
|
86
86
|
"dependencies": [
|
|
87
87
|
"flutter_ota_kit_core",
|
|
88
88
|
"mime"
|
|
@@ -90,7 +90,7 @@
|
|
|
90
90
|
},
|
|
91
91
|
{
|
|
92
92
|
"name": "flutter_ota_kit_core",
|
|
93
|
-
"version": "0.1.
|
|
93
|
+
"version": "0.1.4",
|
|
94
94
|
"dependencies": []
|
|
95
95
|
},
|
|
96
96
|
{
|
|
@@ -81,9 +81,209 @@ Future<int> run(List<String> args) async {
|
|
|
81
81
|
final result = await runner.run(args);
|
|
82
82
|
return result ?? 0;
|
|
83
83
|
} on UsageException catch (e) {
|
|
84
|
+
final msg = e.message;
|
|
85
|
+
|
|
86
|
+
// Missing subcommand → show the command's own help + suggestions.
|
|
87
|
+
if (msg.startsWith('Missing subcommand')) {
|
|
88
|
+
final match = RegExp(r'"flutter-ota (\w+)"').firstMatch(msg);
|
|
89
|
+
if (match != null) {
|
|
90
|
+
final cmd = runner.commands[match.group(1)];
|
|
91
|
+
if (cmd != null) {
|
|
92
|
+
_printMissingSubcommand(cmd);
|
|
93
|
+
return 0;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// No command given → show top-level help.
|
|
99
|
+
if (msg.contains('No command specified')) {
|
|
100
|
+
runner.printUsage();
|
|
101
|
+
return 0;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Unknown command → fuzzy-match and suggest.
|
|
105
|
+
final unknownMatch =
|
|
106
|
+
RegExp(r'Could not find a command named "?(\w+)"?').firstMatch(msg);
|
|
107
|
+
if (unknownMatch != null) {
|
|
108
|
+
final typed = unknownMatch.group(1)!;
|
|
109
|
+
_printUnknownCommand(runner, typed);
|
|
110
|
+
return 64;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Unknown subcommand → suggest closest subcommand.
|
|
114
|
+
final subMatch = RegExp(
|
|
115
|
+
r'Could not find a subcommand named "?(\w+)"? for "?flutter-ota (\w+)"?',
|
|
116
|
+
).firstMatch(msg);
|
|
117
|
+
if (subMatch != null) {
|
|
118
|
+
final subTyped = subMatch.group(1)!;
|
|
119
|
+
final parentName = subMatch.group(2)!;
|
|
120
|
+
final parentCmd = runner.commands[parentName];
|
|
121
|
+
if (parentCmd != null) {
|
|
122
|
+
_printUnknownSubcommand(parentCmd, subTyped);
|
|
123
|
+
return 64;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Fallback — show the raw error + usage.
|
|
84
128
|
stderr.writeln(e.message);
|
|
85
129
|
stderr.writeln('');
|
|
86
130
|
stderr.writeln(e.usage);
|
|
87
131
|
return 64;
|
|
88
132
|
}
|
|
89
133
|
}
|
|
134
|
+
|
|
135
|
+
/// Show a helpful "unknown command" message with fuzzy-match suggestions.
|
|
136
|
+
void _printUnknownCommand(FlutterPatcherRunner runner, String typed) {
|
|
137
|
+
final commands = runner.commands.keys.toList();
|
|
138
|
+
|
|
139
|
+
// Exact prefix match (e.g. "bund" → "bundle").
|
|
140
|
+
final prefixMatches = commands.where((c) => c.startsWith(typed)).toList();
|
|
141
|
+
|
|
142
|
+
// Levenshtein-based fuzzy match for short typos.
|
|
143
|
+
final fuzzyMatches = <String>[];
|
|
144
|
+
for (final c in commands) {
|
|
145
|
+
if (prefixMatches.contains(c)) continue;
|
|
146
|
+
if (_levenshtein(typed, c) <= 2) {
|
|
147
|
+
fuzzyMatches.add(c);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Subcommand matching (e.g. "bundle lis" → suggest "list").
|
|
152
|
+
final subMatch = RegExp(r'^(\w+)\s+(\w+)$').firstMatch(typed);
|
|
153
|
+
String? parentCmd;
|
|
154
|
+
String? subTyped;
|
|
155
|
+
if (subMatch != null) {
|
|
156
|
+
parentCmd = subMatch.group(1);
|
|
157
|
+
subTyped = subMatch.group(2);
|
|
158
|
+
}
|
|
159
|
+
// Also try if typed is just the first part.
|
|
160
|
+
if (parentCmd != null && !commands.contains(parentCmd)) {
|
|
161
|
+
// Check if parentCmd is a fuzzy match for a real command.
|
|
162
|
+
final parentFuzzy = commands.where((c) {
|
|
163
|
+
if (c == parentCmd) return true;
|
|
164
|
+
return _levenshtein(parentCmd!, c) <= 2;
|
|
165
|
+
}).toList();
|
|
166
|
+
if (parentFuzzy.isNotEmpty) {
|
|
167
|
+
parentCmd = parentFuzzy.first;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
stderr.writeln('');
|
|
172
|
+
stderr.writeln(' ${_red('✗')} Unknown command: ${_red(typed)}');
|
|
173
|
+
stderr.writeln('');
|
|
174
|
+
|
|
175
|
+
if (prefixMatches.isNotEmpty || fuzzyMatches.isNotEmpty) {
|
|
176
|
+
final suggestions = [...prefixMatches, ...fuzzyMatches];
|
|
177
|
+
stderr.writeln(' ${_cyan('Did you mean?')}');
|
|
178
|
+
for (final s in suggestions.take(3)) {
|
|
179
|
+
stderr.writeln(' ${_green(s)}');
|
|
180
|
+
}
|
|
181
|
+
stderr.writeln('');
|
|
182
|
+
|
|
183
|
+
// If it looks like "parent sub" but the sub is wrong, show sub help.
|
|
184
|
+
if (parentCmd != null && subTyped != null) {
|
|
185
|
+
final cmd = runner.commands[parentCmd];
|
|
186
|
+
if (cmd != null && cmd.subcommands.isNotEmpty) {
|
|
187
|
+
// Find closest subcommand.
|
|
188
|
+
final subNames = cmd.subcommands.keys.toList();
|
|
189
|
+
final subSuggestion = subNames
|
|
190
|
+
.where((s) => s.startsWith(subTyped!) || _levenshtein(subTyped!, s) <= 2)
|
|
191
|
+
.toList();
|
|
192
|
+
if (subSuggestion.isNotEmpty) {
|
|
193
|
+
stderr.writeln(' ${_cyan('Did you mean?')} $parentCmd ${_green(subSuggestion.first)}');
|
|
194
|
+
stderr.writeln('');
|
|
195
|
+
}
|
|
196
|
+
cmd.printUsage();
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Show top-level help.
|
|
202
|
+
runner.printUsage();
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// No close matches — show all available commands.
|
|
207
|
+
runner.printUsage();
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/// Show a helpful "unknown subcommand" message with suggestions.
|
|
211
|
+
void _printUnknownSubcommand(Command<int> parent, String typed) {
|
|
212
|
+
final subNames = parent.subcommands.keys.toList();
|
|
213
|
+
|
|
214
|
+
// Find closest subcommands.
|
|
215
|
+
final suggestions = subNames
|
|
216
|
+
.where((s) => s.startsWith(typed) || _levenshtein(typed, s) <= 2)
|
|
217
|
+
.toList();
|
|
218
|
+
|
|
219
|
+
stderr.writeln('');
|
|
220
|
+
stderr.writeln(
|
|
221
|
+
' ${_red('✗')} Unknown subcommand: ${_red(typed)} for ${_cyan('flutter-ota ${parent.name}')}',
|
|
222
|
+
);
|
|
223
|
+
stderr.writeln('');
|
|
224
|
+
|
|
225
|
+
if (suggestions.isNotEmpty) {
|
|
226
|
+
stderr.writeln(' ${_cyan('Did you mean?')}');
|
|
227
|
+
for (final s in suggestions.take(3)) {
|
|
228
|
+
stderr.writeln(' ${_green(s)}');
|
|
229
|
+
}
|
|
230
|
+
stderr.writeln('');
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
parent.printUsage();
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/// Show a helpful "missing subcommand" message with all subcommand suggestions.
|
|
237
|
+
void _printMissingSubcommand(Command<int> parent) {
|
|
238
|
+
final subNames = parent.subcommands.keys.toList()..sort();
|
|
239
|
+
|
|
240
|
+
stderr.writeln('');
|
|
241
|
+
stderr.writeln(
|
|
242
|
+
' ${_red('✗')} Missing subcommand for ${_cyan('flutter-ota ${parent.name}')}',
|
|
243
|
+
);
|
|
244
|
+
stderr.writeln('');
|
|
245
|
+
|
|
246
|
+
if (subNames.isNotEmpty) {
|
|
247
|
+
stderr.writeln(' ${_cyan('Did you mean?')}');
|
|
248
|
+
for (final s in subNames) {
|
|
249
|
+
stderr.writeln(' ${_green('${parent.name} $s')}');
|
|
250
|
+
}
|
|
251
|
+
stderr.writeln('');
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
parent.printUsage();
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// ── Minimal Levenshtein distance ──────────────────────────────────────────────
|
|
258
|
+
|
|
259
|
+
int _levenshtein(String a, String b) {
|
|
260
|
+
if (a.isEmpty) return b.length;
|
|
261
|
+
if (b.isEmpty) return a.length;
|
|
262
|
+
final dp = List.generate(a.length + 1, (i) => List.filled(b.length + 1, 0));
|
|
263
|
+
for (var i = 0; i <= a.length; i++) dp[i][0] = i;
|
|
264
|
+
for (var j = 0; j <= b.length; j++) dp[0][j] = j;
|
|
265
|
+
for (var i = 1; i <= a.length; i++) {
|
|
266
|
+
for (var j = 1; j <= b.length; j++) {
|
|
267
|
+
final cost = a[i - 1] == b[j - 1] ? 0 : 1;
|
|
268
|
+
dp[i][j] = [
|
|
269
|
+
dp[i - 1][j] + 1,
|
|
270
|
+
dp[i][j - 1] + 1,
|
|
271
|
+
dp[i - 1][j - 1] + cost,
|
|
272
|
+
].reduce((a, b) => a < b ? a : b);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
return dp[a.length][b.length];
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// ── Minimal inline color helpers (stderr-safe, TTY-aware) ────────────────────
|
|
279
|
+
|
|
280
|
+
bool get _noColor {
|
|
281
|
+
final v = Platform.environment['NO_COLOR'];
|
|
282
|
+
return v != null && v.isNotEmpty;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
bool get _colorOn => !_noColor && stderr.hasTerminal && stderr.supportsAnsiEscapes;
|
|
286
|
+
|
|
287
|
+
String _red(String s) => _colorOn ? '\x1b[31m$s\x1b[0m' : s;
|
|
288
|
+
String _green(String s) => _colorOn ? '\x1b[32m$s\x1b[0m' : s;
|
|
289
|
+
String _cyan(String s) => _colorOn ? '\x1b[36m$s\x1b[0m' : s;
|
|
@@ -59,27 +59,6 @@ class BundleCommand extends FlutterPatcherCommand {
|
|
|
59
59
|
@override
|
|
60
60
|
String get description =>
|
|
61
61
|
'Manage bundles (list / show / delete / disable / enable / force / promote).';
|
|
62
|
-
|
|
63
|
-
@override
|
|
64
|
-
Future<int> run() => runGuarded(() async {
|
|
65
|
-
print(description);
|
|
66
|
-
print('');
|
|
67
|
-
print('Subcommands:');
|
|
68
|
-
print(
|
|
69
|
-
' list List bundles (filters: --channel/-c, --platform/-p, --enabled, --limit/-l)',
|
|
70
|
-
);
|
|
71
|
-
print(' show --id <id> Show a single bundle\'s details');
|
|
72
|
-
print(' delete --id <id> Delete a bundle');
|
|
73
|
-
print(' disable --id <id> Disable a bundle (stop serving it)');
|
|
74
|
-
print(' enable --id <id> Enable a bundle');
|
|
75
|
-
print(
|
|
76
|
-
' force --id <id> Force an update onto clients (--off to clear)',
|
|
77
|
-
);
|
|
78
|
-
print(' promote --id <id> -c Promote a bundle to a channel');
|
|
79
|
-
print(
|
|
80
|
-
' update --id <id> ... Edit metadata (--message/--target-version/--enabled/--force)',
|
|
81
|
-
);
|
|
82
|
-
});
|
|
83
62
|
}
|
|
84
63
|
|
|
85
64
|
class BundleListCommand extends FlutterPatcherCommand {
|
|
@@ -24,16 +24,6 @@ class ChannelCommand extends FlutterPatcherCommand {
|
|
|
24
24
|
|
|
25
25
|
@override
|
|
26
26
|
String get description => 'Manage channels (list / get / set).';
|
|
27
|
-
|
|
28
|
-
@override
|
|
29
|
-
Future<int> run() => runGuarded(() async {
|
|
30
|
-
print(description);
|
|
31
|
-
print('');
|
|
32
|
-
print('Subcommands:');
|
|
33
|
-
print(' list List channels');
|
|
34
|
-
print(' get <channel> Show the live bundle for a channel');
|
|
35
|
-
print(' set <c> <id> Promote a bundle to a channel');
|
|
36
|
-
});
|
|
37
27
|
}
|
|
38
28
|
|
|
39
29
|
class ChannelListCommand extends FlutterPatcherCommand {
|
|
@@ -18,17 +18,6 @@ class ConfigCommand extends FlutterPatcherCommand {
|
|
|
18
18
|
|
|
19
19
|
@override
|
|
20
20
|
String get description => 'Get, set, or list configuration values.';
|
|
21
|
-
|
|
22
|
-
@override
|
|
23
|
-
Future<int> run() => runGuarded(() async {
|
|
24
|
-
// No subcommand selected.
|
|
25
|
-
print(description);
|
|
26
|
-
print('');
|
|
27
|
-
print('Subcommands:');
|
|
28
|
-
print(' get <key>');
|
|
29
|
-
print(' set <key> <value>');
|
|
30
|
-
print(' list');
|
|
31
|
-
});
|
|
32
21
|
}
|
|
33
22
|
|
|
34
23
|
Map<String, dynamic> _loadProjectJson() {
|
|
@@ -59,6 +48,7 @@ class ConfigGetCommand extends FlutterPatcherCommand {
|
|
|
59
48
|
|
|
60
49
|
@override
|
|
61
50
|
Future<int> run() => runGuarded(() async {
|
|
51
|
+
ui.banner('config · get');
|
|
62
52
|
final key = argResults!['key'] as String? ??
|
|
63
53
|
(argResults!.rest.isNotEmpty ? argResults!.rest.first : null);
|
|
64
54
|
if (key == null || key.isEmpty) {
|
|
@@ -66,7 +56,7 @@ class ConfigGetCommand extends FlutterPatcherCommand {
|
|
|
66
56
|
}
|
|
67
57
|
final value = readPath(_loadProjectJson(), key);
|
|
68
58
|
if (value == null) {
|
|
69
|
-
|
|
59
|
+
ui.warn('(not set)');
|
|
70
60
|
return;
|
|
71
61
|
}
|
|
72
62
|
stdout.writeln(
|
|
@@ -39,6 +39,7 @@ class ConsoleCommand extends FlutterPatcherCommand {
|
|
|
39
39
|
return;
|
|
40
40
|
}
|
|
41
41
|
if (argResults!['open'] as bool) {
|
|
42
|
+
banner('console · open');
|
|
42
43
|
step('Launching console...');
|
|
43
44
|
final process = await Process.start(
|
|
44
45
|
'flutter',
|
|
@@ -47,7 +48,8 @@ class ConsoleCommand extends FlutterPatcherCommand {
|
|
|
47
48
|
runInShell: true,
|
|
48
49
|
mode: ProcessStartMode.inheritStdio,
|
|
49
50
|
);
|
|
50
|
-
|
|
51
|
+
final code = await process.exitCode;
|
|
52
|
+
if (code != 0) err('flutter run exited with code $code');
|
|
51
53
|
return;
|
|
52
54
|
}
|
|
53
55
|
banner('console');
|
|
@@ -73,11 +73,7 @@ class DeployCommand extends FlutterPatcherCommand {
|
|
|
73
73
|
final bundleId = argResults!['bundle-id'] as String?;
|
|
74
74
|
|
|
75
75
|
banner('deploy');
|
|
76
|
-
|
|
77
|
-
' ${gray('channel')} ${cyan(channel)} '
|
|
78
|
-
'${gray('platform')} ${cyan(platform)} '
|
|
79
|
-
'${gray('source')} ${dim(source)}',
|
|
80
|
-
);
|
|
76
|
+
info('channel ${cyan(channel)} platform ${cyan(platform)} source ${dim(source)}');
|
|
81
77
|
|
|
82
78
|
final bundle = await spinner(
|
|
83
79
|
() => deployBundle(
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import 'dart:io';
|
|
2
|
-
|
|
3
|
-
|
|
4
1
|
import '../cli_base.dart';
|
|
2
|
+
import '../ui/ui.dart';
|
|
5
3
|
import '../util.dart';
|
|
6
4
|
|
|
7
5
|
/// `flutter_ota_kit fingerprint` — compute a build-time fingerprint hash.
|
|
@@ -24,8 +22,9 @@ class FingerprintCommand extends FlutterPatcherCommand {
|
|
|
24
22
|
|
|
25
23
|
@override
|
|
26
24
|
Future<int> run() => runGuarded(() async {
|
|
25
|
+
banner(name);
|
|
27
26
|
final source = argResults!['source'] as String;
|
|
28
27
|
final hash = generateFingerprint(source);
|
|
29
|
-
|
|
28
|
+
box('fingerprint', [kv('source', source), kv('hash', hash)]);
|
|
30
29
|
});
|
|
31
30
|
}
|
|
@@ -248,10 +248,8 @@ class InitCommand extends FlutterPatcherCommand {
|
|
|
248
248
|
step('Wrote ${file.path}');
|
|
249
249
|
|
|
250
250
|
if (global) {
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
'Restrict permissions and use a secrets manager in production.',
|
|
254
|
-
);
|
|
251
|
+
warn('Secrets are stored in plaintext under ~/.flutter_ota_kit. '
|
|
252
|
+
'Restrict permissions and use a secrets manager in production.');
|
|
255
253
|
return;
|
|
256
254
|
}
|
|
257
255
|
|
|
@@ -259,35 +257,23 @@ class InitCommand extends FlutterPatcherCommand {
|
|
|
259
257
|
await _scaffoldProject(cfg, provider);
|
|
260
258
|
|
|
261
259
|
stdout.writeln();
|
|
262
|
-
stdout.writeln(cyan('Next steps:'));
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
stdout.writeln(
|
|
269
|
-
' A `.env` scaffold was written — put secrets there, then build with '
|
|
270
|
-
'`--dart-define-from-file=.env` (environment overrides config).',
|
|
271
|
-
);
|
|
260
|
+
stdout.writeln(' ${cyan('Next steps:')}');
|
|
261
|
+
step('1. ${dim('flutter pub get')}');
|
|
262
|
+
step('2. In lib/main.dart call ${green('await setupFlutterOta();')} '
|
|
263
|
+
'right after WidgetsFlutterBinding.ensureInitialized() (before runApp). '
|
|
264
|
+
'A `.env` scaffold was written — put secrets there, then build with '
|
|
265
|
+
'`--dart-define-from-file=.env` (environment overrides config).');
|
|
272
266
|
if (provider == 'supabase') {
|
|
273
|
-
|
|
274
|
-
' 3. Provision the backend once: ${dim('flutter-ota migrate supabase')}',
|
|
275
|
-
);
|
|
267
|
+
step('3. Provision the backend once: ${dim('flutter-ota migrate supabase')}');
|
|
276
268
|
} else if (provider == 'postgres') {
|
|
277
|
-
|
|
278
|
-
' 3. Provision the backend: ${dim('flutter-ota migrate postgres')}',
|
|
279
|
-
);
|
|
269
|
+
step('3. Provision the backend: ${dim('flutter-ota migrate postgres')}');
|
|
280
270
|
} else if (provider == 'pocketbase') {
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
'${dim('flutter-ota pocketbase serve')}.',
|
|
285
|
-
);
|
|
271
|
+
step('3. Install PocketBase + provision the schema: '
|
|
272
|
+
'${dim('flutter-ota pocketbase install')} then '
|
|
273
|
+
'${dim('flutter-ota pocketbase serve')}.');
|
|
286
274
|
}
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
'then ${dim('flutter-ota deploy')}',
|
|
290
|
-
);
|
|
275
|
+
step('4. Build a patch: ${dim('flutter-ota build --name 1.0.1')} '
|
|
276
|
+
'then ${dim('flutter-ota deploy')}');
|
|
291
277
|
});
|
|
292
278
|
|
|
293
279
|
/// Generate the integration files (pubspec dep, manifest permission, setup dart
|
|
@@ -306,9 +292,7 @@ class InitCommand extends FlutterPatcherCommand {
|
|
|
306
292
|
void _addPubDependency() {
|
|
307
293
|
final pubspec = File('pubspec.yaml');
|
|
308
294
|
if (!pubspec.existsSync()) {
|
|
309
|
-
|
|
310
|
-
yellow(' ⚠ pubspec.yaml not found; skipping dependency injection.'),
|
|
311
|
-
);
|
|
295
|
+
warn('pubspec.yaml not found; skipping dependency injection.');
|
|
312
296
|
return;
|
|
313
297
|
}
|
|
314
298
|
var content = pubspec.readAsStringSync();
|
|
@@ -320,11 +304,7 @@ class InitCommand extends FlutterPatcherCommand {
|
|
|
320
304
|
final marker = '\ndependencies:';
|
|
321
305
|
final idx = content.indexOf(marker);
|
|
322
306
|
if (idx == -1) {
|
|
323
|
-
|
|
324
|
-
yellow(
|
|
325
|
-
' ⚠ could not find a `dependencies:` block; add `flutter_ota_kit` manually.',
|
|
326
|
-
),
|
|
327
|
-
);
|
|
307
|
+
warn('Could not find a `dependencies:` block; add `flutter_ota_kit` manually.');
|
|
328
308
|
return;
|
|
329
309
|
}
|
|
330
310
|
final insertAt = idx + marker.length;
|
|
@@ -336,11 +316,7 @@ class InitCommand extends FlutterPatcherCommand {
|
|
|
336
316
|
void _addInternetPermission() {
|
|
337
317
|
final mf = File('android/app/src/main/AndroidManifest.xml');
|
|
338
318
|
if (!mf.existsSync()) {
|
|
339
|
-
|
|
340
|
-
yellow(
|
|
341
|
-
' ⚠ AndroidManifest.xml not found; skipping INTERNET permission.',
|
|
342
|
-
),
|
|
343
|
-
);
|
|
319
|
+
warn('AndroidManifest.xml not found; skipping INTERNET permission.');
|
|
344
320
|
return;
|
|
345
321
|
}
|
|
346
322
|
var content = mf.readAsStringSync();
|
|
@@ -350,11 +326,7 @@ class InitCommand extends FlutterPatcherCommand {
|
|
|
350
326
|
}
|
|
351
327
|
final match = RegExp(r'<manifest[^>]*>').firstMatch(content);
|
|
352
328
|
if (match == null) {
|
|
353
|
-
|
|
354
|
-
yellow(
|
|
355
|
-
' ⚠ could not locate <manifest> tag; add INTERNET permission manually.',
|
|
356
|
-
),
|
|
357
|
-
);
|
|
329
|
+
warn('Could not locate <manifest> tag; add INTERNET permission manually.');
|
|
358
330
|
return;
|
|
359
331
|
}
|
|
360
332
|
final insertAt = match.end;
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import 'dart:convert';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
import '../backend.dart';
|
|
5
3
|
import '../cli_base.dart';
|
|
6
4
|
import '../config.dart';
|
|
7
5
|
import '../sign.dart';
|
|
@@ -9,13 +7,10 @@ import '../ui/ui.dart';
|
|
|
9
7
|
|
|
10
8
|
/// `flutter_ota_kit keys` — generate an Ed25519 keypair for bundle signing.
|
|
11
9
|
class KeysCommand extends FlutterPatcherCommand {
|
|
12
|
-
KeysCommand(
|
|
10
|
+
KeysCommand() {
|
|
13
11
|
argParser.addFlag('save', help: 'Persist the public key into the project config.');
|
|
14
12
|
}
|
|
15
13
|
|
|
16
|
-
final FlutterPatcherConfig? config;
|
|
17
|
-
final Backend? backendOverride;
|
|
18
|
-
|
|
19
14
|
@override
|
|
20
15
|
String get name => 'keys';
|
|
21
16
|
|
|
@@ -202,6 +202,7 @@ class PocketBaseStopCommand extends FlutterPatcherCommand {
|
|
|
202
202
|
|
|
203
203
|
@override
|
|
204
204
|
Future<int> run() => runGuarded(() async {
|
|
205
|
+
banner('pocketbase · stop');
|
|
205
206
|
step('Use Ctrl+C on the running serve process to stop PocketBase.');
|
|
206
207
|
return;
|
|
207
208
|
});
|
|
@@ -216,6 +217,7 @@ class PocketBaseStatusCommand extends FlutterPatcherCommand {
|
|
|
216
217
|
|
|
217
218
|
@override
|
|
218
219
|
Future<int> run() => runGuarded(() async {
|
|
220
|
+
banner('pocketbase · status');
|
|
219
221
|
final paths = PocketBaseInstallPaths.resolve();
|
|
220
222
|
final exists = await paths.binaryPath.exists();
|
|
221
223
|
if (exists) {
|
|
@@ -18,8 +18,22 @@ class FlutterPatcherRunner extends CommandRunner<int> {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
@override
|
|
21
|
-
Future<int?> runCommand(ArgResults results) {
|
|
21
|
+
Future<int?> runCommand(ArgResults results) async {
|
|
22
22
|
verboseMode = results['verbose'] as bool? ?? false;
|
|
23
|
+
|
|
24
|
+
// Intercept missing subcommand for parent commands so we show our
|
|
25
|
+
// colored usage text instead of the args package's plain text.
|
|
26
|
+
if (results.command == null && results.rest.isEmpty) {
|
|
27
|
+
final cmdName = results.arguments.isNotEmpty ? results.arguments.first : null;
|
|
28
|
+
if (cmdName != null) {
|
|
29
|
+
final cmd = commands[cmdName];
|
|
30
|
+
if (cmd != null && cmd.subcommands.isNotEmpty) {
|
|
31
|
+
cmd.printUsage();
|
|
32
|
+
return 0;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
23
37
|
return super.runCommand(results);
|
|
24
38
|
}
|
|
25
39
|
|
|
@@ -99,6 +99,8 @@ void banner(String name) {
|
|
|
99
99
|
void step(String msg) => _echo(' ${green('✓')} $msg');
|
|
100
100
|
void warn(String msg) => _echo(' ${yellow('⚠')} ${yellow(msg)}');
|
|
101
101
|
void err(String msg) => _echo(' ${red('✗')} ${red(msg)}');
|
|
102
|
+
void info(String msg) => _echo(' ${blue('ℹ')} $msg');
|
|
103
|
+
void active(String msg) => _echo(' ${cyan('⠹')} $msg');
|
|
102
104
|
|
|
103
105
|
// ── Spinner ──────────────────────────────────────────────────────────────────
|
|
104
106
|
|
|
@@ -116,13 +118,18 @@ Future<T> spinner<T>(
|
|
|
116
118
|
return r;
|
|
117
119
|
}
|
|
118
120
|
var i = 0;
|
|
121
|
+
final sw = Stopwatch()..start();
|
|
119
122
|
final timer = Timer.periodic(const Duration(milliseconds: 80), (_) {
|
|
120
123
|
i = (i + 1) % _frames.length;
|
|
121
124
|
stdout.write('\r\x1b[K ${cyan(_frames[i])} $label');
|
|
122
125
|
});
|
|
123
126
|
try {
|
|
124
127
|
final r = await task();
|
|
128
|
+
// Keep spinner visible for at least 400ms so fast ops are readable.
|
|
129
|
+
final elapsed = sw.elapsedMilliseconds;
|
|
130
|
+
if (elapsed < 400) await Future.delayed(Duration(milliseconds: 400 - elapsed));
|
|
125
131
|
timer.cancel();
|
|
132
|
+
sw.stop();
|
|
126
133
|
stdout.write('\r\x1b[K ${green('✓')} ${done ?? label}\n');
|
|
127
134
|
return r;
|
|
128
135
|
} catch (e) {
|
|
@@ -232,12 +239,12 @@ void box(String title, List<String> lines) {
|
|
|
232
239
|
final leftDashes = math.max(1, totalDashes ~/ 2);
|
|
233
240
|
final rightDashes = totalDashes - leftDashes;
|
|
234
241
|
|
|
235
|
-
_echo('
|
|
242
|
+
_echo('┌${'─' * leftDashes}$titleText${'─' * rightDashes}┐');
|
|
236
243
|
for (final l in wrapped) {
|
|
237
244
|
final pad = math.max(0, inner - _dispWidth(l));
|
|
238
245
|
_echo('│ $l${' ' * pad} │');
|
|
239
246
|
}
|
|
240
|
-
_echo('
|
|
247
|
+
_echo('└${'─' * (width - 2)}┘');
|
|
241
248
|
}
|
|
242
249
|
|
|
243
250
|
// ── Steps ────────────────────────────────────────────────────────────────────
|
|
@@ -304,9 +311,9 @@ class Steps {
|
|
|
304
311
|
|
|
305
312
|
// ── Progress Bar (thin, single-line) ────────────────────────────────────────
|
|
306
313
|
|
|
307
|
-
///
|
|
314
|
+
/// Braille single-line progress bar with spinner, label, bar, and time.
|
|
308
315
|
///
|
|
309
|
-
/// Renders as: `⠹ Label
|
|
316
|
+
/// Renders as: `⠹ Label ⣿⣿⣿⣀⣀⣀ 50%`
|
|
310
317
|
/// On finish: `✓ Label in 1.3s`
|
|
311
318
|
class ProgressBar {
|
|
312
319
|
ProgressBar(this.total, this.label);
|
|
@@ -335,11 +342,11 @@ class ProgressBar {
|
|
|
335
342
|
|
|
336
343
|
final pct = total > 0 ? (_current / total).clamp(0.0, 1.0) : 1.0;
|
|
337
344
|
|
|
338
|
-
//
|
|
345
|
+
// Braille bar: width scales to terminal, max 20 chars.
|
|
339
346
|
final barW = math.min(20, math.max(8, _cols - 40));
|
|
340
347
|
final filled = (barW * pct).round();
|
|
341
348
|
final empty = barW - filled;
|
|
342
|
-
final bar = '${yellow('
|
|
349
|
+
final bar = '${yellow('⣿' * filled)}${gray('⣀' * empty)}';
|
|
343
350
|
|
|
344
351
|
_spin = (_spin + 1) % _frames.length;
|
|
345
352
|
final pctStr = '${(pct * 100).round()}%'.padLeft(4);
|
|
@@ -349,10 +356,17 @@ class ProgressBar {
|
|
|
349
356
|
);
|
|
350
357
|
}
|
|
351
358
|
|
|
352
|
-
|
|
359
|
+
/// Finish: print the final status line. This is intentionally async and
|
|
360
|
+
/// fire-and-forget (called without `await` from [update] and [close]).
|
|
361
|
+
/// The 500ms delay keeps fast ops readable; if the process exits early,
|
|
362
|
+
/// the final line may not print — acceptable for a CLI progress aid.
|
|
363
|
+
void _finish() async {
|
|
353
364
|
if (_closed) return;
|
|
354
365
|
_closed = true;
|
|
355
366
|
_sw.stop();
|
|
367
|
+
// Keep bar visible for at least 500ms so fast ops are readable.
|
|
368
|
+
final elapsed = _sw.elapsedMilliseconds;
|
|
369
|
+
if (elapsed < 500) await Future.delayed(Duration(milliseconds: 500 - elapsed));
|
|
356
370
|
final ms = _sw.elapsedMilliseconds;
|
|
357
371
|
final time = ms >= 1000
|
|
358
372
|
? '${(ms / 1000).toStringAsFixed(1)}s'
|
|
@@ -159,49 +159,49 @@ packages:
|
|
|
159
159
|
path: "../../plugins/aws"
|
|
160
160
|
relative: true
|
|
161
161
|
source: path
|
|
162
|
-
version: "0.1.
|
|
162
|
+
version: "0.1.5"
|
|
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.5"
|
|
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.4"
|
|
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.6"
|
|
184
184
|
flutter_ota_kit_pocketbase:
|
|
185
185
|
dependency: "direct main"
|
|
186
186
|
description:
|
|
187
187
|
path: "../../plugins/pocketbase"
|
|
188
188
|
relative: true
|
|
189
189
|
source: path
|
|
190
|
-
version: "0.1.
|
|
190
|
+
version: "0.1.2"
|
|
191
191
|
flutter_ota_kit_postgres:
|
|
192
192
|
dependency: "direct main"
|
|
193
193
|
description:
|
|
194
194
|
path: "../../plugins/postgres"
|
|
195
195
|
relative: true
|
|
196
196
|
source: path
|
|
197
|
-
version: "0.1.
|
|
197
|
+
version: "0.1.5"
|
|
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.6"
|
|
205
205
|
frontend_server_client:
|
|
206
206
|
dependency: transitive
|
|
207
207
|
description:
|
|
@@ -1,12 +1 @@
|
|
|
1
|
-
## 0.1.
|
|
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
|
-
|
|
10
|
-
## 0.1.0
|
|
11
|
-
|
|
12
|
-
- Initial release of `flutter_ota_kit_core` as part of the flutter_ota_kit OTA toolkit.
|
|
1
|
+
## 0.1.4
|
|
@@ -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.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
|
|
@@ -1,18 +1 @@
|
|
|
1
|
-
## 0.1.
|
|
2
|
-
|
|
3
|
-
- Add dartdoc on internal API surfaces (10/10 pana dartdoc coverage).
|
|
4
|
-
|
|
5
|
-
## 0.1.2
|
|
6
|
-
|
|
7
|
-
- Bump `pointycastle` to `^4.0.0` (API-compatible, security update).
|
|
8
|
-
- Add `withCloudFrontSignedUrl` helper for time-limited download URLs.
|
|
9
|
-
- Add `defaultAwsCloudFrontClientFactory` export.
|
|
10
|
-
- Repository moved to `https://github.com/HYPER12755/flutter-ota-kit`.
|
|
11
|
-
|
|
12
|
-
## 0.1.1
|
|
13
|
-
|
|
14
|
-
- Initial test release of the AWS S3 + CloudFront storage plugin.
|
|
15
|
-
|
|
16
|
-
## 0.1.0
|
|
17
|
-
|
|
18
|
-
- Initial release of `flutter_ota_kit_aws` as part of the flutter_ota_kit OTA toolkit.
|
|
1
|
+
## 0.1.5
|
|
@@ -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.5
|
|
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,18 +1 @@
|
|
|
1
|
-
## 0.1.
|
|
2
|
-
|
|
3
|
-
- Add dartdoc on internal API surfaces (10/10 pana dartdoc coverage).
|
|
4
|
-
|
|
5
|
-
## 0.1.2
|
|
6
|
-
|
|
7
|
-
- Add `parseMetadata` / `parseTargetCohorts` exports from the D1 bundle
|
|
8
|
-
mapper for writing custom Cloudflare Worker logic.
|
|
9
|
-
- Add `defaultRolloutCohortCount` export.
|
|
10
|
-
- Repository moved to `https://github.com/HYPER12755/flutter-ota-kit`.
|
|
11
|
-
|
|
12
|
-
## 0.1.1
|
|
13
|
-
|
|
14
|
-
- Initial test release of the Cloudflare D1 + R2 storage plugin.
|
|
15
|
-
|
|
16
|
-
## 0.1.0
|
|
17
|
-
|
|
18
|
-
- Initial release of `flutter_ota_kit_cloudflare` as part of the flutter_ota_kit OTA toolkit.
|
|
1
|
+
## 0.1.5
|
|
@@ -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.5
|
|
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,17 +1 @@
|
|
|
1
|
-
## 0.0.
|
|
2
|
-
|
|
3
|
-
- Add dartdoc on internal API surfaces (10/10 pana dartdoc coverage).
|
|
4
|
-
|
|
5
|
-
## 0.0.3
|
|
6
|
-
|
|
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
|
|
12
|
-
|
|
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
|
+
## 0.0.6
|
|
@@ -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.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,8 +1 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
## 0.1.0
|
|
4
|
-
|
|
5
|
-
- Initial release of `flutter_ota_kit_pocketbase` — PocketBase
|
|
6
|
-
database + storage plugins for the flutter_ota_kit OTA toolkit.
|
|
7
|
-
See the [PocketBase backend guide](https://github.com/HYPER12755/flutter-ota-kit/blob/main/doc/backends.md#pocketbase)
|
|
8
|
-
for usage.
|
|
1
|
+
## 0.1.2
|
|
@@ -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.
|
|
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,19 +1 @@
|
|
|
1
|
-
## 0.1.
|
|
2
|
-
|
|
3
|
-
- Add dartdoc on internal API surfaces (10/10 pana dartdoc coverage).
|
|
4
|
-
|
|
5
|
-
## 0.1.2
|
|
6
|
-
|
|
7
|
-
- Add `PostgresBundleRow` + `mapRowToBundle` exports for writing custom server
|
|
8
|
-
tooling on top of `flutter_ota_kit_postgres`.
|
|
9
|
-
- Repository moved to `https://github.com/HYPER12755/flutter-ota-kit`.
|
|
10
|
-
|
|
11
|
-
## 0.1.1
|
|
12
|
-
|
|
13
|
-
- Throw a clear `StateError` from `getDownloadUrl` when no `servingBaseUrl`
|
|
14
|
-
is configured (previously the URL silently failed).
|
|
15
|
-
- Remove dead `IS NULL` filter paths in `_buildWhere`.
|
|
16
|
-
|
|
17
|
-
## 0.1.0
|
|
18
|
-
|
|
19
|
-
- Initial release of `flutter_ota_kit_postgres` as part of the flutter_ota_kit OTA toolkit.
|
|
1
|
+
## 0.1.5
|
|
@@ -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.
|
|
3
|
+
version: 0.1.5
|
|
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,23 +1 @@
|
|
|
1
|
-
## 0.1.
|
|
2
|
-
|
|
3
|
-
- Add dartdoc on internal API surfaces (10/10 pana dartdoc coverage).
|
|
4
|
-
|
|
5
|
-
## 0.1.3
|
|
6
|
-
|
|
7
|
-
- Export `SupabaseBundleRow` and `mapRowToBundle` for writing custom server
|
|
8
|
-
tooling on top of `flutter_ota_kit_supabase`.
|
|
9
|
-
- Repository moved to `https://github.com/HYPER12755/flutter-ota-kit`.
|
|
10
|
-
|
|
11
|
-
## 0.1.2
|
|
12
|
-
|
|
13
|
-
- Add edge-function database + storage variants (`supabaseEdgeFunctionDatabase`,
|
|
14
|
-
`supabaseEdgeFunctionStorage`).
|
|
15
|
-
- Add `createSupabaseSignedUrlBatcher` for signed-URL time-bounded downloads.
|
|
16
|
-
|
|
17
|
-
## 0.1.1
|
|
18
|
-
|
|
19
|
-
- Initial test release of the Supabase storage plugin.
|
|
20
|
-
|
|
21
|
-
## 0.1.0
|
|
22
|
-
|
|
23
|
-
- Initial release of `flutter_ota_kit_supabase` as part of the flutter_ota_kit OTA toolkit.
|
|
1
|
+
## 0.1.6
|
|
@@ -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.
|
|
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
|
package/package.json
CHANGED
package/scripts/vendor.sh
CHANGED
|
File without changes
|