@_nazmiforreal/flutter-ota 0.1.14 → 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/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/test/cli_test.dart +6 -0
- 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
|
Binary file
|
package/bin/flutter-ota.js
CHANGED
|
@@ -1,85 +1,36 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
//
|
|
6
|
-
// Resolves a platform+arch-specific prebuilt binary (`flutter-ota-<os>-<arch>`)
|
|
7
|
-
// shipped next to this script, falling back to `dart run` of the bundled Dart
|
|
8
|
-
// source when no prebuilt exists for the current architecture (e.g. a user on
|
|
9
|
-
// arm64 with only an x64 binary present). This keeps the package installable on
|
|
10
|
-
// any platform that has the Dart SDK, without us needing to ship every binary.
|
|
11
|
-
|
|
12
|
-
const { spawnSync } = require('child_process');
|
|
13
|
-
const fs = require('fs');
|
|
4
|
+
const { execFileSync } = require('child_process');
|
|
14
5
|
const path = require('path');
|
|
6
|
+
const os = require('os');
|
|
15
7
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
if (process.platform === 'darwin') return 'macos';
|
|
19
|
-
return 'linux';
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function arch() {
|
|
23
|
-
// Only x64/arm64 matter for Dart AOT; everything else falls back to Dart VM.
|
|
24
|
-
return process.arch === 'arm64' ? 'arm64' : 'x64';
|
|
25
|
-
}
|
|
8
|
+
const platform = os.platform();
|
|
9
|
+
const arch = os.arch();
|
|
26
10
|
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
11
|
+
const binaryNames = {
|
|
12
|
+
'linux-x64': 'flutter-ota-linux-x64',
|
|
13
|
+
'linux-arm64': 'flutter-ota-linux-arm64',
|
|
14
|
+
'darwin-x64': 'flutter-ota-darwin-x64',
|
|
15
|
+
'darwin-arm64': 'flutter-ota-darwin-arm64',
|
|
16
|
+
'win32-x64': 'flutter-ota-win32-x64.exe',
|
|
17
|
+
};
|
|
33
18
|
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
);
|
|
37
|
-
const cliDir = path.dirname(path.dirname(sourceEntry));
|
|
19
|
+
const key = `${platform}-${arch}`;
|
|
20
|
+
const binName = binaryNames[key];
|
|
38
21
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
// Ensure owner-executable bit is set.
|
|
43
|
-
if (!(st.mode & 0o100)) fs.chmodSync(p, st.mode | 0o755);
|
|
44
|
-
} catch (_) {
|
|
45
|
-
// Non-fatal.
|
|
46
|
-
}
|
|
22
|
+
if (!binName) {
|
|
23
|
+
console.error(`flutter-ota: unsupported platform ${platform}-${arch}`);
|
|
24
|
+
process.exit(1);
|
|
47
25
|
}
|
|
48
26
|
|
|
49
|
-
|
|
50
|
-
const res = spawnSync(bin, args, { stdio: 'inherit', windowsHide: false });
|
|
51
|
-
process.exit(res.status == null ? 1 : res.status);
|
|
52
|
-
}
|
|
27
|
+
const binPath = path.join(__dirname, binName);
|
|
53
28
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
fs.existsSync(sourceEntry)
|
|
60
|
-
) {
|
|
61
|
-
// Ensure dependencies are resolved before running from source. We only run
|
|
62
|
-
// `dart pub get` when the package config is missing, so repeated invocations
|
|
63
|
-
// don't re-resolve dependencies on every command.
|
|
64
|
-
const configPath = path.join(cliDir, '.dart_tool', 'package_config.json');
|
|
65
|
-
if (!fs.existsSync(configPath)) {
|
|
66
|
-
const getRes = spawnSync('dart', ['pub', 'get'], { stdio: 'inherit', cwd: cliDir });
|
|
67
|
-
if (getRes.status !== 0) {
|
|
68
|
-
console.error(
|
|
69
|
-
'flutter-ota: `dart pub get` failed. Install dependencies or build ' +
|
|
70
|
-
`a prebuilt manually:\n cd ${cliDir} && dart compile exe ` +
|
|
71
|
-
`bin/flutter_ota_kit.dart -o ${binPath}`,
|
|
72
|
-
);
|
|
73
|
-
process.exit(1);
|
|
74
|
-
}
|
|
29
|
+
try {
|
|
30
|
+
execFileSync(binPath, process.argv.slice(2), { stdio: 'inherit' });
|
|
31
|
+
} catch (err) {
|
|
32
|
+
if (err.status !== undefined) {
|
|
33
|
+
process.exit(err.status);
|
|
75
34
|
}
|
|
76
|
-
|
|
77
|
-
run('dart', [sourceEntry, ...process.argv.slice(2)]);
|
|
78
|
-
} else {
|
|
79
|
-
console.error(
|
|
80
|
-
`flutter-ota: no prebuilt binary for ${platformName}-${archName} and ` +
|
|
81
|
-
'the Dart SDK was not found. Install Dart (https://dart.dev) or use a ' +
|
|
82
|
-
'platform/arch with a shipped prebuilt binary.',
|
|
83
|
-
);
|
|
84
|
-
process.exit(1);
|
|
35
|
+
throw err;
|
|
85
36
|
}
|
|
@@ -59,8 +59,8 @@ import 'src/commands/storage.dart';
|
|
|
59
59
|
Future<int> run(List<String> args) async {
|
|
60
60
|
final runner =
|
|
61
61
|
FlutterPatcherRunner(
|
|
62
|
-
'
|
|
63
|
-
'
|
|
62
|
+
'flutter-ota',
|
|
63
|
+
'flutter-ota CLI — OTA code push for Flutter (hot-updater compatible).',
|
|
64
64
|
)
|
|
65
65
|
..addCommand(InitCommand())
|
|
66
66
|
..addCommand(ConfigCommand())
|
|
@@ -1,9 +1,26 @@
|
|
|
1
|
-
import 'package:args/args.dart';
|
|
2
1
|
import 'package:flutter_ota_kit_cli/flutter_ota_kit_cli.dart';
|
|
3
2
|
|
|
4
3
|
import '../ui/ui.dart';
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
final _uuidRe = RegExp(
|
|
6
|
+
r'^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$',
|
|
7
|
+
caseSensitive: false,
|
|
8
|
+
);
|
|
9
|
+
|
|
10
|
+
void _requireUuid(String? id, String command) {
|
|
11
|
+
if (id == null || id.isEmpty) {
|
|
12
|
+
throw PackException('Usage: flutter-ota bundle $command --id <id>', 64);
|
|
13
|
+
}
|
|
14
|
+
if (!_uuidRe.hasMatch(id)) {
|
|
15
|
+
throw PackException(
|
|
16
|
+
'Invalid UUID format: "$id". '
|
|
17
|
+
'Expected: 8-4-4-4-12 hex digits.',
|
|
18
|
+
64,
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/// `flutter-ota bundle` — manage bundles entirely from the CLI (no direct
|
|
7
24
|
/// DB access needed; the CLI talks to the backend through its plugins).
|
|
8
25
|
class BundleCommand extends FlutterPatcherCommand {
|
|
9
26
|
BundleCommand({this.config, this.backendOverride}) {
|
|
@@ -66,7 +83,13 @@ class BundleCommand extends FlutterPatcherCommand {
|
|
|
66
83
|
}
|
|
67
84
|
|
|
68
85
|
class BundleListCommand extends FlutterPatcherCommand {
|
|
69
|
-
BundleListCommand({this.config, this.backendOverride})
|
|
86
|
+
BundleListCommand({this.config, this.backendOverride}) {
|
|
87
|
+
argParser.addOption('backend', abbr: 'b', help: 'Backend provider.');
|
|
88
|
+
argParser.addOption('channel', abbr: 'c', help: 'Filter by channel.');
|
|
89
|
+
argParser.addOption('platform', abbr: 'p', help: 'Filter by platform.');
|
|
90
|
+
argParser.addOption('enabled', help: 'Filter by enabled (true/false).');
|
|
91
|
+
argParser.addOption('limit', abbr: 'l', defaultsTo: '20', help: 'Page size.');
|
|
92
|
+
}
|
|
70
93
|
|
|
71
94
|
final FlutterPatcherConfig? config;
|
|
72
95
|
final Backend? backendOverride;
|
|
@@ -77,14 +100,6 @@ class BundleListCommand extends FlutterPatcherCommand {
|
|
|
77
100
|
@override
|
|
78
101
|
String get description => 'List bundles.';
|
|
79
102
|
|
|
80
|
-
@override
|
|
81
|
-
ArgParser get argParser => ArgParser()
|
|
82
|
-
..addOption('backend', abbr: 'b', help: 'Backend provider.')
|
|
83
|
-
..addOption('channel', abbr: 'c', help: 'Filter by channel.')
|
|
84
|
-
..addOption('platform', abbr: 'p', help: 'Filter by platform.')
|
|
85
|
-
..addOption('enabled', help: 'Filter by enabled (true/false).')
|
|
86
|
-
..addOption('limit', abbr: 'l', defaultsTo: '20', help: 'Page size.');
|
|
87
|
-
|
|
88
103
|
@override
|
|
89
104
|
Future<int> run() => runGuarded(() async {
|
|
90
105
|
final cfg = effectiveConfig(config ?? loadConfig(), argResults!);
|
|
@@ -93,13 +108,18 @@ class BundleListCommand extends FlutterPatcherCommand {
|
|
|
93
108
|
final enabled = enabledRaw == null
|
|
94
109
|
? null
|
|
95
110
|
: (enabledRaw == 'true' || enabledRaw == '1');
|
|
111
|
+
final limitRaw = argResults!['limit'] as String;
|
|
112
|
+
final limit = int.tryParse(limitRaw);
|
|
113
|
+
if (limit == null || limit < 1) {
|
|
114
|
+
throw PackException('--limit must be a positive integer (got "$limitRaw")', 64);
|
|
115
|
+
}
|
|
96
116
|
final res = await listBundles(
|
|
97
117
|
backend,
|
|
98
118
|
ListOptions(
|
|
99
119
|
channel: argResults!['channel'] as String?,
|
|
100
120
|
platform: argResults!['platform'] as String?,
|
|
101
121
|
enabled: enabled,
|
|
102
|
-
limit:
|
|
122
|
+
limit: limit,
|
|
103
123
|
),
|
|
104
124
|
);
|
|
105
125
|
banner('bundle · list');
|
|
@@ -107,30 +127,33 @@ class BundleListCommand extends FlutterPatcherCommand {
|
|
|
107
127
|
step('(no bundles)');
|
|
108
128
|
return;
|
|
109
129
|
}
|
|
110
|
-
final
|
|
130
|
+
final rows = <List<String>>[];
|
|
111
131
|
for (var i = 0; i < res.data.length; i++) {
|
|
112
132
|
final b = res.data[i];
|
|
113
|
-
final
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
lines.add(kv('signature', green('✓ signed')));
|
|
124
|
-
}
|
|
125
|
-
lines.add('');
|
|
133
|
+
final enabled = b.enabled ? green('✓') : red('✗');
|
|
134
|
+
final force = b.shouldForceUpdate ? green('✓') : dim('✗');
|
|
135
|
+
rows.add([
|
|
136
|
+
'$i',
|
|
137
|
+
cyan(b.id),
|
|
138
|
+
b.channel,
|
|
139
|
+
b.platform.value,
|
|
140
|
+
force,
|
|
141
|
+
enabled,
|
|
142
|
+
]);
|
|
126
143
|
}
|
|
127
|
-
|
|
128
|
-
|
|
144
|
+
table(
|
|
145
|
+
'${res.data.length} bundles (total: ${res.pagination.total})',
|
|
146
|
+
['#', 'ID', 'CHANNEL', 'PLAT', 'FORCE', 'ON'],
|
|
147
|
+
rows,
|
|
148
|
+
);
|
|
129
149
|
});
|
|
130
150
|
}
|
|
131
151
|
|
|
132
152
|
class BundleShowCommand extends FlutterPatcherCommand {
|
|
133
|
-
BundleShowCommand({this.config, this.backendOverride})
|
|
153
|
+
BundleShowCommand({this.config, this.backendOverride}) {
|
|
154
|
+
argParser.addOption('backend', abbr: 'b', help: 'Backend provider.');
|
|
155
|
+
argParser.addOption('id', help: 'Bundle id.');
|
|
156
|
+
}
|
|
134
157
|
|
|
135
158
|
final FlutterPatcherConfig? config;
|
|
136
159
|
final Backend? backendOverride;
|
|
@@ -141,21 +164,14 @@ class BundleShowCommand extends FlutterPatcherCommand {
|
|
|
141
164
|
@override
|
|
142
165
|
String get description => 'Show a single bundle\'s details.';
|
|
143
166
|
|
|
144
|
-
@override
|
|
145
|
-
ArgParser get argParser => ArgParser()
|
|
146
|
-
..addOption('backend', abbr: 'b', help: 'Backend provider.')
|
|
147
|
-
..addOption('id', help: 'Bundle id.');
|
|
148
|
-
|
|
149
167
|
@override
|
|
150
168
|
Future<int> run() => runGuarded(() async {
|
|
151
169
|
final id = argResults!['id'] as String?;
|
|
152
|
-
|
|
153
|
-
throw PackException('Usage: flutter_ota_kit bundle show --id <id>', 64);
|
|
154
|
-
}
|
|
170
|
+
_requireUuid(id, 'show');
|
|
155
171
|
final cfg = effectiveConfig(config ?? loadConfig(), argResults!);
|
|
156
172
|
final backend = requireBackend(cfg, override: backendOverride);
|
|
157
173
|
banner('bundle · show');
|
|
158
|
-
final b = await backend.db.getBundleById(id);
|
|
174
|
+
final b = await backend.db.getBundleById(id!);
|
|
159
175
|
if (b == null) {
|
|
160
176
|
step('(not found)');
|
|
161
177
|
return;
|
|
@@ -177,7 +193,15 @@ class BundleShowCommand extends FlutterPatcherCommand {
|
|
|
177
193
|
}
|
|
178
194
|
|
|
179
195
|
class BundleDeleteCommand extends FlutterPatcherCommand {
|
|
180
|
-
BundleDeleteCommand({this.config, this.backendOverride})
|
|
196
|
+
BundleDeleteCommand({this.config, this.backendOverride}) {
|
|
197
|
+
argParser.addOption('backend', abbr: 'b', help: 'Backend provider.');
|
|
198
|
+
argParser.addOption('id', help: 'Bundle id.');
|
|
199
|
+
argParser.addFlag(
|
|
200
|
+
'keep-storage',
|
|
201
|
+
help: 'Do not delete the storage object.',
|
|
202
|
+
negatable: false,
|
|
203
|
+
);
|
|
204
|
+
}
|
|
181
205
|
|
|
182
206
|
final FlutterPatcherConfig? config;
|
|
183
207
|
final Backend? backendOverride;
|
|
@@ -188,47 +212,42 @@ class BundleDeleteCommand extends FlutterPatcherCommand {
|
|
|
188
212
|
@override
|
|
189
213
|
String get description => 'Delete a bundle by id.';
|
|
190
214
|
|
|
191
|
-
@override
|
|
192
|
-
ArgParser get argParser => ArgParser()
|
|
193
|
-
..addOption('backend', abbr: 'b', help: 'Backend provider.')
|
|
194
|
-
..addOption('id', help: 'Bundle id.')
|
|
195
|
-
..addFlag(
|
|
196
|
-
'keep-storage',
|
|
197
|
-
help: 'Do not delete the storage object.',
|
|
198
|
-
negatable: false,
|
|
199
|
-
);
|
|
200
|
-
|
|
201
215
|
@override
|
|
202
216
|
Future<int> run() => runGuarded(() async {
|
|
203
217
|
final id = argResults!['id'] as String?;
|
|
204
|
-
|
|
205
|
-
throw PackException('Usage: flutter_ota_kit bundle delete --id <id>', 64);
|
|
206
|
-
}
|
|
218
|
+
_requireUuid(id, 'delete');
|
|
207
219
|
final cfg = effectiveConfig(config ?? loadConfig(), argResults!);
|
|
208
220
|
final backend = requireBackend(cfg, override: backendOverride);
|
|
209
221
|
banner('bundle · delete');
|
|
210
|
-
final existing = await backend.db.getBundleById(id);
|
|
222
|
+
final existing = await backend.db.getBundleById(id!);
|
|
211
223
|
if (existing == null) {
|
|
212
224
|
throw StateError('Bundle "$id" not found.');
|
|
213
225
|
}
|
|
214
226
|
final keepStorage = argResults!['keep-storage'] as bool;
|
|
227
|
+
final steps = Steps('delete');
|
|
215
228
|
await spinner(
|
|
216
229
|
() => deleteBundle(backend, id),
|
|
217
230
|
'Deleting bundle $id',
|
|
218
231
|
done: 'Deleted',
|
|
219
232
|
);
|
|
233
|
+
steps.success('Deleted bundle $id');
|
|
220
234
|
if (!keepStorage && existing.storageUri.isNotEmpty) {
|
|
221
235
|
await spinner(
|
|
222
236
|
() => backend.storage.delete(existing.storageUri),
|
|
223
237
|
'Removing storage object',
|
|
224
238
|
done: 'Storage removed',
|
|
225
239
|
);
|
|
240
|
+
steps.success('Removed storage object');
|
|
226
241
|
}
|
|
242
|
+
steps.summary();
|
|
227
243
|
});
|
|
228
244
|
}
|
|
229
245
|
|
|
230
246
|
class BundleDisableCommand extends FlutterPatcherCommand {
|
|
231
|
-
BundleDisableCommand({this.config, this.backendOverride})
|
|
247
|
+
BundleDisableCommand({this.config, this.backendOverride}) {
|
|
248
|
+
argParser.addOption('backend', abbr: 'b', help: 'Backend provider.');
|
|
249
|
+
argParser.addOption('id', help: 'Bundle id.');
|
|
250
|
+
}
|
|
232
251
|
|
|
233
252
|
final FlutterPatcherConfig? config;
|
|
234
253
|
final Backend? backendOverride;
|
|
@@ -239,26 +258,16 @@ class BundleDisableCommand extends FlutterPatcherCommand {
|
|
|
239
258
|
@override
|
|
240
259
|
String get description => 'Disable a bundle (stop serving it).';
|
|
241
260
|
|
|
242
|
-
@override
|
|
243
|
-
ArgParser get argParser => ArgParser()
|
|
244
|
-
..addOption('backend', abbr: 'b', help: 'Backend provider.')
|
|
245
|
-
..addOption('id', help: 'Bundle id.');
|
|
246
|
-
|
|
247
261
|
@override
|
|
248
262
|
Future<int> run() => runGuarded(() async {
|
|
249
263
|
final id = argResults!['id'] as String?;
|
|
250
|
-
|
|
251
|
-
throw PackException(
|
|
252
|
-
'Usage: flutter_ota_kit bundle disable --id <id>',
|
|
253
|
-
64,
|
|
254
|
-
);
|
|
255
|
-
}
|
|
264
|
+
_requireUuid(id, 'disable');
|
|
256
265
|
final cfg = effectiveConfig(config ?? loadConfig(), argResults!);
|
|
257
266
|
final backend = requireBackend(cfg, override: backendOverride);
|
|
258
267
|
banner('bundle · disable');
|
|
259
268
|
await spinner(
|
|
260
269
|
() async {
|
|
261
|
-
await backend.db.updateBundle(id
|
|
270
|
+
await backend.db.updateBundle(id!, {'enabled': false});
|
|
262
271
|
await backend.db.commitBundle();
|
|
263
272
|
},
|
|
264
273
|
'Disabling bundle $id',
|
|
@@ -268,7 +277,10 @@ class BundleDisableCommand extends FlutterPatcherCommand {
|
|
|
268
277
|
}
|
|
269
278
|
|
|
270
279
|
class BundleEnableCommand extends FlutterPatcherCommand {
|
|
271
|
-
BundleEnableCommand({this.config, this.backendOverride})
|
|
280
|
+
BundleEnableCommand({this.config, this.backendOverride}) {
|
|
281
|
+
argParser.addOption('backend', abbr: 'b', help: 'Backend provider.');
|
|
282
|
+
argParser.addOption('id', help: 'Bundle id.');
|
|
283
|
+
}
|
|
272
284
|
|
|
273
285
|
final FlutterPatcherConfig? config;
|
|
274
286
|
final Backend? backendOverride;
|
|
@@ -279,23 +291,16 @@ class BundleEnableCommand extends FlutterPatcherCommand {
|
|
|
279
291
|
@override
|
|
280
292
|
String get description => 'Enable a bundle.';
|
|
281
293
|
|
|
282
|
-
@override
|
|
283
|
-
ArgParser get argParser => ArgParser()
|
|
284
|
-
..addOption('backend', abbr: 'b', help: 'Backend provider.')
|
|
285
|
-
..addOption('id', help: 'Bundle id.');
|
|
286
|
-
|
|
287
294
|
@override
|
|
288
295
|
Future<int> run() => runGuarded(() async {
|
|
289
296
|
final id = argResults!['id'] as String?;
|
|
290
|
-
|
|
291
|
-
throw PackException('Usage: flutter_ota_kit bundle enable --id <id>', 64);
|
|
292
|
-
}
|
|
297
|
+
_requireUuid(id, 'enable');
|
|
293
298
|
final cfg = effectiveConfig(config ?? loadConfig(), argResults!);
|
|
294
299
|
final backend = requireBackend(cfg, override: backendOverride);
|
|
295
300
|
banner('bundle · enable');
|
|
296
301
|
await spinner(
|
|
297
302
|
() async {
|
|
298
|
-
await backend.db.updateBundle(id
|
|
303
|
+
await backend.db.updateBundle(id!, {'enabled': true});
|
|
299
304
|
await backend.db.commitBundle();
|
|
300
305
|
},
|
|
301
306
|
'Enabling bundle $id',
|
|
@@ -305,7 +310,14 @@ class BundleEnableCommand extends FlutterPatcherCommand {
|
|
|
305
310
|
}
|
|
306
311
|
|
|
307
312
|
class BundleForceCommand extends FlutterPatcherCommand {
|
|
308
|
-
BundleForceCommand({this.config, this.backendOverride})
|
|
313
|
+
BundleForceCommand({this.config, this.backendOverride}) {
|
|
314
|
+
argParser.addOption('backend', abbr: 'b', help: 'Backend provider.');
|
|
315
|
+
argParser.addOption('id', help: 'Bundle id.');
|
|
316
|
+
argParser.addFlag(
|
|
317
|
+
'off',
|
|
318
|
+
help: 'Clear the force-update flag instead of setting it.',
|
|
319
|
+
);
|
|
320
|
+
}
|
|
309
321
|
|
|
310
322
|
final FlutterPatcherConfig? config;
|
|
311
323
|
final Backend? backendOverride;
|
|
@@ -316,31 +328,17 @@ class BundleForceCommand extends FlutterPatcherCommand {
|
|
|
316
328
|
@override
|
|
317
329
|
String get description => 'Force an update onto clients (--off to clear).';
|
|
318
330
|
|
|
319
|
-
@override
|
|
320
|
-
ArgParser get argParser => ArgParser()
|
|
321
|
-
..addOption('backend', abbr: 'b', help: 'Backend provider.')
|
|
322
|
-
..addOption('id', help: 'Bundle id.')
|
|
323
|
-
..addFlag(
|
|
324
|
-
'off',
|
|
325
|
-
help: 'Clear the force-update flag instead of setting it.',
|
|
326
|
-
);
|
|
327
|
-
|
|
328
331
|
@override
|
|
329
332
|
Future<int> run() => runGuarded(() async {
|
|
330
333
|
final id = argResults!['id'] as String?;
|
|
331
|
-
|
|
332
|
-
throw PackException(
|
|
333
|
-
'Usage: flutter_ota_kit bundle force --id <id> [--off]',
|
|
334
|
-
64,
|
|
335
|
-
);
|
|
336
|
-
}
|
|
334
|
+
_requireUuid(id, 'force');
|
|
337
335
|
final off = argResults!['off'] as bool;
|
|
338
336
|
final cfg = effectiveConfig(config ?? loadConfig(), argResults!);
|
|
339
337
|
final backend = requireBackend(cfg, override: backendOverride);
|
|
340
338
|
banner('bundle · force');
|
|
341
339
|
await spinner(
|
|
342
340
|
() async {
|
|
343
|
-
await backend.db.updateBundle(id
|
|
341
|
+
await backend.db.updateBundle(id!, {
|
|
344
342
|
'shouldForceUpdate': !off,
|
|
345
343
|
if (!off) 'enabled': true,
|
|
346
344
|
});
|
|
@@ -353,7 +351,11 @@ class BundleForceCommand extends FlutterPatcherCommand {
|
|
|
353
351
|
}
|
|
354
352
|
|
|
355
353
|
class BundlePromoteCommand extends FlutterPatcherCommand {
|
|
356
|
-
BundlePromoteCommand({this.config, this.backendOverride})
|
|
354
|
+
BundlePromoteCommand({this.config, this.backendOverride}) {
|
|
355
|
+
argParser.addOption('backend', abbr: 'b', help: 'Backend provider.');
|
|
356
|
+
argParser.addOption('id', help: 'Bundle id.');
|
|
357
|
+
argParser.addOption('channel', abbr: 'c', help: 'Target channel.');
|
|
358
|
+
}
|
|
357
359
|
|
|
358
360
|
final FlutterPatcherConfig? config;
|
|
359
361
|
final Backend? backendOverride;
|
|
@@ -364,19 +366,14 @@ class BundlePromoteCommand extends FlutterPatcherCommand {
|
|
|
364
366
|
@override
|
|
365
367
|
String get description => 'Promote a bundle to a channel.';
|
|
366
368
|
|
|
367
|
-
@override
|
|
368
|
-
ArgParser get argParser => ArgParser()
|
|
369
|
-
..addOption('backend', abbr: 'b', help: 'Backend provider.')
|
|
370
|
-
..addOption('id', help: 'Bundle id.')
|
|
371
|
-
..addOption('channel', abbr: 'c', help: 'Target channel.');
|
|
372
|
-
|
|
373
369
|
@override
|
|
374
370
|
Future<int> run() => runGuarded(() async {
|
|
375
371
|
final id = argResults!['id'] as String?;
|
|
376
372
|
final channel = argResults!['channel'] as String?;
|
|
377
|
-
|
|
373
|
+
_requireUuid(id, 'promote');
|
|
374
|
+
if (channel == null || channel.isEmpty) {
|
|
378
375
|
throw PackException(
|
|
379
|
-
'Usage:
|
|
376
|
+
'Usage: flutter-ota bundle promote --id <id> --channel <channel>',
|
|
380
377
|
64,
|
|
381
378
|
);
|
|
382
379
|
}
|
|
@@ -384,16 +381,23 @@ class BundlePromoteCommand extends FlutterPatcherCommand {
|
|
|
384
381
|
final backend = requireBackend(cfg, override: backendOverride);
|
|
385
382
|
banner('bundle · promote');
|
|
386
383
|
await spinner(
|
|
387
|
-
() => promoteBundle(backend, id
|
|
384
|
+
() => promoteBundle(backend, id!, channel),
|
|
388
385
|
'Promoting $id to $channel',
|
|
389
386
|
done: 'Promoted',
|
|
390
387
|
);
|
|
391
|
-
box('promote', [kv('bundle', cyan(id)), kv('channel', channel)]);
|
|
388
|
+
box('promote', [kv('bundle', cyan(id!)), kv('channel', channel)]);
|
|
392
389
|
});
|
|
393
390
|
}
|
|
394
391
|
|
|
395
392
|
class BundleUpdateCommand extends FlutterPatcherCommand {
|
|
396
|
-
BundleUpdateCommand({this.config, this.backendOverride})
|
|
393
|
+
BundleUpdateCommand({this.config, this.backendOverride}) {
|
|
394
|
+
argParser.addOption('backend', abbr: 'b', help: 'Backend provider.');
|
|
395
|
+
argParser.addOption('id', help: 'Bundle id.');
|
|
396
|
+
argParser.addOption('message', abbr: 'm', help: 'New release message.');
|
|
397
|
+
argParser.addOption('target-version', help: 'New target app version (e.g. 1.0.0).');
|
|
398
|
+
argParser.addOption('enabled', help: 'Set enabled (true/false).');
|
|
399
|
+
argParser.addOption('force', abbr: 'f', help: 'Set force-update (true/false).');
|
|
400
|
+
}
|
|
397
401
|
|
|
398
402
|
final FlutterPatcherConfig? config;
|
|
399
403
|
final Backend? backendOverride;
|
|
@@ -405,26 +409,10 @@ class BundleUpdateCommand extends FlutterPatcherCommand {
|
|
|
405
409
|
String get description =>
|
|
406
410
|
'Edit a bundle\'s metadata (message / target version / enabled / force).';
|
|
407
411
|
|
|
408
|
-
@override
|
|
409
|
-
ArgParser get argParser => ArgParser()
|
|
410
|
-
..addOption('backend', abbr: 'b', help: 'Backend provider.')
|
|
411
|
-
..addOption('id', help: 'Bundle id.')
|
|
412
|
-
..addOption('message', abbr: 'm', help: 'New release message.')
|
|
413
|
-
..addOption('target-version', help: 'New target app version (e.g. 1.0.0).')
|
|
414
|
-
..addOption('enabled', help: 'Set enabled (true/false).')
|
|
415
|
-
..addOption('force', abbr: 'f', help: 'Set force-update (true/false).');
|
|
416
|
-
|
|
417
412
|
@override
|
|
418
413
|
Future<int> run() => runGuarded(() async {
|
|
419
414
|
final id = argResults!['id'] as String?;
|
|
420
|
-
|
|
421
|
-
throw PackException(
|
|
422
|
-
'Usage: flutter-ota bundle update --id <id> '
|
|
423
|
-
'[--message <m>] [--target-version <v>] [--enabled true|false] '
|
|
424
|
-
'[--force true|false]',
|
|
425
|
-
64,
|
|
426
|
-
);
|
|
427
|
-
}
|
|
415
|
+
_requireUuid(id, 'update');
|
|
428
416
|
final patch = <String, Object?>{};
|
|
429
417
|
final message = argResults!['message'] as String?;
|
|
430
418
|
if (message != null) patch['message'] = message;
|
|
@@ -446,13 +434,13 @@ class BundleUpdateCommand extends FlutterPatcherCommand {
|
|
|
446
434
|
banner('bundle · update');
|
|
447
435
|
await spinner(
|
|
448
436
|
() async {
|
|
449
|
-
await backend.db.updateBundle(id
|
|
437
|
+
await backend.db.updateBundle(id!, patch);
|
|
450
438
|
await backend.db.commitBundle();
|
|
451
439
|
},
|
|
452
440
|
'Updating $id',
|
|
453
441
|
done: 'Updated',
|
|
454
442
|
);
|
|
455
|
-
final b = await backend.db.getBundleById(id);
|
|
443
|
+
final b = await backend.db.getBundleById(id!);
|
|
456
444
|
if (b != null) {
|
|
457
445
|
box('bundle', [
|
|
458
446
|
kv('id', cyan(b.id)),
|