@_nazmiforreal/flutter-ota 0.1.27 → 0.1.29
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/README.md +112 -18
- package/bin/flutter-ota-linux-x64 +0 -0
- package/dart-src/packages/cli-tools/README.md +146 -2
- package/dart-src/packages/cli-tools/lib/src/commands/init.dart +36 -8
- package/dart-src/packages/cli-tools/pubspec.yaml +1 -1
- package/dart-src/root/README.md +193 -253
- package/dart-src/root/android/src/main/kotlin/com/flutter_patcher/flutter_patcher/PatchManager.kt +24 -5
- package/dart-src/root/lib/src/ota_progress_overlay.dart +176 -96
- package/dart-src/root/pubspec.yaml +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,37 +1,131 @@
|
|
|
1
|
-
# flutter-ota
|
|
1
|
+
# flutter-ota
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@_nazmiforreal/flutter-ota)
|
|
4
|
+
[](https://github.com/HYPER12755/flutter-ota-kit/blob/main/LICENSE)
|
|
5
|
+
|
|
6
|
+
### The command line for [flutter_ota_kit](https://pub.dev/packages/flutter_ota_kit) — build patches, deploy them to your backend, and manage rollouts.
|
|
7
|
+
|
|
8
|
+
`flutter-ota` is the companion CLI for **flutter_ota_kit**, open-source OTA code
|
|
9
|
+
push for Flutter Android. Pack a release APK into a signed patch, upload it to
|
|
10
|
+
the backend **you** own (Supabase / Postgres / Cloudflare / AWS / PocketBase),
|
|
11
|
+
and manage channels, staged rollouts, and instant rollback — no store review, no
|
|
12
|
+
monthly bill.
|
|
13
|
+
|
|
14
|
+
> The runtime SDK your app depends on is the separate
|
|
15
|
+
> [`flutter_ota_kit`](https://pub.dev/packages/flutter_ota_kit) pub package.
|
|
16
|
+
|
|
17
|
+
---
|
|
4
18
|
|
|
5
19
|
## Install
|
|
6
20
|
|
|
7
21
|
```bash
|
|
8
22
|
npm i -g @_nazmiforreal/flutter-ota
|
|
23
|
+
flutter-ota --help
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
A prebuilt `linux-x64` binary ships in the package. On other platforms the CLI
|
|
27
|
+
compiles from bundled Dart source on first install, which needs the
|
|
28
|
+
[**Flutter SDK**](https://flutter.dev) (the CLI shares the `flutter_ota_kit`
|
|
29
|
+
Flutter package). If Flutter isn't available, build a binary once yourself:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
cd $(npm root -g)/@_nazmiforreal/flutter-ota/dart-src/packages/cli-tools
|
|
33
|
+
flutter pub get && dart compile exe bin/flutter_ota_kit.dart -o ../../bin/flutter-ota-<os>-<arch>
|
|
9
34
|
```
|
|
10
35
|
|
|
11
|
-
|
|
36
|
+
---
|
|
12
37
|
|
|
13
|
-
##
|
|
38
|
+
## The 60-second workflow
|
|
14
39
|
|
|
15
40
|
```bash
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
flutter-ota
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
41
|
+
# 1. Scaffold config + a setup helper for your backend
|
|
42
|
+
# (adds the latest flutter_ota_kit to your pubspec automatically)
|
|
43
|
+
flutter-ota init supabase # or: postgres | cloudflare | aws | pocketbase
|
|
44
|
+
|
|
45
|
+
# 2. Provision the backend (Supabase & PocketBase are fully automated)
|
|
46
|
+
flutter-ota migrate supabase
|
|
47
|
+
|
|
48
|
+
# 3. Build the release APK, then pack it into a device-ready patch
|
|
49
|
+
flutter build apk --release
|
|
50
|
+
flutter-ota build \
|
|
51
|
+
--apk build/app/outputs/flutter-apk/app-release.apk \
|
|
52
|
+
--version 1.0.1 \
|
|
53
|
+
--target-version-code 100
|
|
54
|
+
|
|
55
|
+
# 4. Sign + deploy it to a channel
|
|
56
|
+
flutter-ota deploy --source dist --channel production \
|
|
57
|
+
--target-app-version 1.0.0 --force -m "hotfix: crash on login"
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Devices pick up the patch on their next launch. Pull it back with:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
flutter-ota rollback --channel production
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Commands
|
|
69
|
+
|
|
70
|
+
| Command | What it does |
|
|
71
|
+
|---------|--------------|
|
|
72
|
+
| `init <backend>` | Scaffold config, `.env`, and `lib/flutter_ota_kit_setup.dart`; add the SDK dependency + `INTERNET` permission |
|
|
73
|
+
| `build` | Pack a release APK into `dist/patch.zip` (all ABIs by default) |
|
|
74
|
+
| `deploy` | Upload + register a bundle; sign it with `--key` |
|
|
75
|
+
| `bundle` | `list` / `show` / `delete` / `disable` / `enable` / `force` / `promote` / `update` |
|
|
76
|
+
| `channel` | `list` / `get` / `set` the live bundle per channel |
|
|
77
|
+
| `rollback` | Disable the latest enabled bundle (or roll back to a specific one) |
|
|
78
|
+
| `storage` | `list` / `delete` stored bundle objects |
|
|
79
|
+
| `migrate` | Provision the backend schema |
|
|
80
|
+
| `keys` | Generate an Ed25519 signing keypair |
|
|
81
|
+
| `fingerprint` | Compute a deterministic build fingerprint |
|
|
82
|
+
| `doctor` | Diagnose the environment + backend connectivity |
|
|
83
|
+
| `config` | `get` / `set` / `list` config values |
|
|
84
|
+
| `console` | Open the web console |
|
|
85
|
+
| `pocketbase` | Manage a local single-binary PocketBase backend |
|
|
86
|
+
|
|
87
|
+
Help works at every level, including nested subcommands:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
flutter-ota deploy --help
|
|
91
|
+
flutter-ota bundle list --help
|
|
92
|
+
flutter-ota pocketbase records list --help
|
|
23
93
|
```
|
|
24
94
|
|
|
25
|
-
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Backends
|
|
98
|
+
|
|
99
|
+
Select one with `--backend supabase|postgres|cloudflare|aws|pocketbase` (or set
|
|
100
|
+
`provider` in `.flutter_ota_kit/config.json`). Settings resolve with a clear
|
|
101
|
+
precedence:
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
explicit flag > environment variable > .flutter_ota_kit/config.json > default
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Config search order: `./.flutter_ota_kit/config.json`, then
|
|
108
|
+
`~/.flutter_ota_kit/config.json`. Secrets belong in your shell env or `.env`,
|
|
109
|
+
never in committed config.
|
|
110
|
+
|
|
111
|
+
| Backend | Provisioning |
|
|
112
|
+
|---------|--------------|
|
|
113
|
+
| **Supabase** | `migrate supabase` — SQL + storage bucket, fully automated |
|
|
114
|
+
| **PocketBase** | `pocketbase install` + `pocketbase serve` — single binary, schema auto-installed |
|
|
115
|
+
| **Postgres** | `migrate postgres` applies SQL migrations |
|
|
116
|
+
| **Cloudflare** | `migrate cloudflare` creates D1 + R2, runs SQL |
|
|
117
|
+
| **AWS** | No SQL — S3 bucket/prefix created on first `deploy` |
|
|
118
|
+
|
|
119
|
+
---
|
|
26
120
|
|
|
27
|
-
|
|
28
|
-
Each resolves its own env / `.flutter_ota_kit/config.json` (global: `~/.flutter_ota_kit/config.json`).
|
|
121
|
+
## Documentation
|
|
29
122
|
|
|
30
|
-
|
|
123
|
+
- [CLI Reference](https://github.com/HYPER12755/flutter-ota-kit/blob/main/doc/cli-reference.md)
|
|
124
|
+
- [Getting Started](https://github.com/HYPER12755/flutter-ota-kit/blob/main/doc/getting-started.md)
|
|
125
|
+
- [Backends](https://github.com/HYPER12755/flutter-ota-kit/blob/main/doc/backends.md)
|
|
126
|
+
- [Production Playbook](https://github.com/HYPER12755/flutter-ota-kit/blob/main/doc/production-playbook.md)
|
|
31
127
|
|
|
32
|
-
|
|
33
|
-
`rollback`, `channel` (list/get/set), `fingerprint`, `doctor`, `migrate`, `config`
|
|
34
|
-
(get/set/list), `keys`, `console`, `storage` (list/delete).
|
|
128
|
+
---
|
|
35
129
|
|
|
36
130
|
## License
|
|
37
131
|
|
|
Binary file
|
|
@@ -1,5 +1,149 @@
|
|
|
1
1
|
# flutter_ota_kit_cli
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@_nazmiforreal/flutter-ota)
|
|
4
|
+
[](../../LICENSE)
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
### The command line for [flutter_ota_kit](https://pub.dev/packages/flutter_ota_kit) — build patches, deploy them to your backend, and manage rollouts.
|
|
7
|
+
|
|
8
|
+
`flutter-ota` is the companion CLI for **flutter_ota_kit**, open-source OTA code
|
|
9
|
+
push for Flutter Android. It packs a release APK into a signed patch, uploads it
|
|
10
|
+
to the backend **you** own (Supabase / Postgres / Cloudflare / AWS / PocketBase),
|
|
11
|
+
and gives you first-class commands for channels, staged rollouts, and instant
|
|
12
|
+
rollback.
|
|
13
|
+
|
|
14
|
+
> This tool ships via npm as `@_nazmiforreal/flutter-ota`. The runtime SDK your
|
|
15
|
+
> app depends on is the separate [`flutter_ota_kit`](https://pub.dev/packages/flutter_ota_kit)
|
|
16
|
+
> pub package.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Install
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm i -g @_nazmiforreal/flutter-ota
|
|
24
|
+
flutter-ota --help
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
A prebuilt `linux-x64` binary ships in the package. On other platforms the CLI
|
|
28
|
+
compiles from bundled Dart source on first install, which needs the
|
|
29
|
+
[**Flutter SDK**](https://flutter.dev) (the CLI shares the `flutter_ota_kit`
|
|
30
|
+
package). No Flutter? Point `flutter-ota` at a prebuilt binary you build once
|
|
31
|
+
with `dart compile exe`.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## The 60-second workflow
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
# 1. Scaffold config + a setup helper for your backend (adds the latest
|
|
39
|
+
# flutter_ota_kit to your pubspec automatically)
|
|
40
|
+
flutter-ota init supabase # or: postgres | cloudflare | aws | pocketbase
|
|
41
|
+
|
|
42
|
+
# 2. Provision the backend (Supabase & PocketBase are fully automated)
|
|
43
|
+
flutter-ota migrate supabase
|
|
44
|
+
|
|
45
|
+
# 3. Build the release APK, then pack it into a device-ready patch
|
|
46
|
+
flutter build apk --release
|
|
47
|
+
flutter-ota build \
|
|
48
|
+
--apk build/app/outputs/flutter-apk/app-release.apk \
|
|
49
|
+
--version 1.0.1 \
|
|
50
|
+
--target-version-code 100
|
|
51
|
+
|
|
52
|
+
# 4. Sign + deploy it to a channel
|
|
53
|
+
flutter-ota deploy --source dist --channel production \
|
|
54
|
+
--target-app-version 1.0.0 --force -m "hotfix: crash on login"
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Devices pick up the patch on their next launch. To pull it back:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
flutter-ota rollback --channel production
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Commands
|
|
66
|
+
|
|
67
|
+
| Command | What it does |
|
|
68
|
+
|---------|--------------|
|
|
69
|
+
| `init <backend>` | Scaffold `.flutter_ota_kit/config.json`, `.env`, and `lib/flutter_ota_kit_setup.dart`; add the SDK dependency + `INTERNET` permission |
|
|
70
|
+
| `build` | Pack a release APK into a device-ready `dist/patch.zip` (all ABIs by default) |
|
|
71
|
+
| `deploy` | Upload + register a bundle; sign it with `--key` |
|
|
72
|
+
| `bundle` | `list` / `show` / `delete` / `disable` / `enable` / `force` / `promote` / `update` |
|
|
73
|
+
| `channel` | `list` / `get` / `set` the live bundle per channel |
|
|
74
|
+
| `rollback` | Disable the latest enabled bundle on a channel (or roll back to a specific one) |
|
|
75
|
+
| `storage` | `list` / `delete` stored bundle objects |
|
|
76
|
+
| `migrate` | Provision the backend schema (Supabase / Postgres / Cloudflare / AWS / PocketBase) |
|
|
77
|
+
| `keys` | Generate an Ed25519 signing keypair |
|
|
78
|
+
| `fingerprint` | Compute a deterministic build fingerprint for fingerprint-targeted rollouts |
|
|
79
|
+
| `doctor` | Diagnose the environment + backend connectivity |
|
|
80
|
+
| `config` | `get` / `set` / `list` config values |
|
|
81
|
+
| `console` | Open the web console |
|
|
82
|
+
| `pocketbase` | Manage a local single-binary PocketBase backend (install / serve / …) |
|
|
83
|
+
|
|
84
|
+
Every command has help, including nested subcommands:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
flutter-ota deploy --help
|
|
88
|
+
flutter-ota bundle list --help
|
|
89
|
+
flutter-ota pocketbase records list --help
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Meaningful short flags map to the option's own name — e.g. on `deploy`:
|
|
93
|
+
`-s`ource, `-c`hannel, `-m`essage, `-f`orce, `-t`arget-app-version,
|
|
94
|
+
`-k`ey, `-b`ackend.
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Backends
|
|
99
|
+
|
|
100
|
+
Select one with `--backend supabase|postgres|cloudflare|aws|pocketbase` (or set
|
|
101
|
+
`provider` in `.flutter_ota_kit/config.json`). Each resolves settings with a
|
|
102
|
+
clear precedence:
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
explicit flag > environment variable > .flutter_ota_kit/config.json > default
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Config file search order: `./.flutter_ota_kit/config.json`, then the global
|
|
109
|
+
`~/.flutter_ota_kit/config.json`. Secrets (service-role keys, DB passwords,
|
|
110
|
+
tokens) belong in your shell environment or `.env` — never in committed config.
|
|
111
|
+
|
|
112
|
+
| Backend | Provisioning |
|
|
113
|
+
|---------|--------------|
|
|
114
|
+
| **Supabase** | `migrate supabase` runs SQL + creates the storage bucket — fully automated |
|
|
115
|
+
| **PocketBase** | `pocketbase install` + `pocketbase serve` — single binary, schema auto-installed |
|
|
116
|
+
| **Postgres** | `migrate postgres` applies the SQL migrations |
|
|
117
|
+
| **Cloudflare** | `migrate cloudflare` creates D1 + R2 and runs SQL |
|
|
118
|
+
| **AWS** | No SQL — the S3 bucket/prefix is created on first `deploy` |
|
|
119
|
+
|
|
120
|
+
See the [Backends guide](https://github.com/HYPER12755/flutter-ota-kit/blob/main/doc/backends.md)
|
|
121
|
+
for per-backend env vars and setup.
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## Signing
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
flutter-ota keys --save # generate a keypair, save the public half
|
|
129
|
+
flutter-ota deploy --key <private-file> # sign the bundle (Ed25519 over the MD5)
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Put the public key in your app via `FlutterPatcher.init(publicKeyBase64: '…')`;
|
|
133
|
+
keep the private key on your CI/build machine, never in the app bundle.
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Documentation
|
|
138
|
+
|
|
139
|
+
- [CLI Reference](https://github.com/HYPER12755/flutter-ota-kit/blob/main/doc/cli-reference.md) — every command + flag
|
|
140
|
+
- [Getting Started](https://github.com/HYPER12755/flutter-ota-kit/blob/main/doc/getting-started.md)
|
|
141
|
+
- [Backends](https://github.com/HYPER12755/flutter-ota-kit/blob/main/doc/backends.md)
|
|
142
|
+
- [Configuration](https://github.com/HYPER12755/flutter-ota-kit/blob/main/doc/configuration.md)
|
|
143
|
+
- [Production Playbook](https://github.com/HYPER12755/flutter-ota-kit/blob/main/doc/production-playbook.md)
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## License
|
|
148
|
+
|
|
149
|
+
MIT
|
|
@@ -314,24 +314,52 @@ class InitCommand extends FlutterPatcherCommand {
|
|
|
314
314
|
warn('pubspec.yaml not found; skipping dependency injection.');
|
|
315
315
|
return;
|
|
316
316
|
}
|
|
317
|
-
|
|
317
|
+
final content = pubspec.readAsStringSync();
|
|
318
318
|
if (content.contains(RegExp(r'^\s*flutter_ota_kit\s*:', multiLine: true))) {
|
|
319
319
|
step('pubspec.yaml already references flutter_ota_kit');
|
|
320
320
|
return;
|
|
321
321
|
}
|
|
322
|
-
|
|
322
|
+
// Prefer `flutter pub add`, which resolves the LATEST published version and
|
|
323
|
+
// writes a proper caret constraint — so the CLI never hardcodes (and never
|
|
324
|
+
// goes stale on) a version number.
|
|
325
|
+
final exe = _flutterOrDart();
|
|
326
|
+
if (exe != null) {
|
|
327
|
+
final res = Process.runSync(exe, ['pub', 'add', 'flutter_ota_kit']);
|
|
328
|
+
if (res.exitCode == 0) {
|
|
329
|
+
step('Added `flutter_ota_kit` (latest) via `$exe pub add`');
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
warn('`$exe pub add flutter_ota_kit` failed; falling back to a manual '
|
|
333
|
+
'edit. Run it yourself if the constraint looks wrong.');
|
|
334
|
+
}
|
|
335
|
+
// Fallback: append an unpinned dependency so `pub get` picks the latest
|
|
336
|
+
// compatible release. Still no hardcoded version.
|
|
323
337
|
final marker = '\ndependencies:';
|
|
324
338
|
final idx = content.indexOf(marker);
|
|
325
339
|
if (idx == -1) {
|
|
326
|
-
warn(
|
|
327
|
-
|
|
328
|
-
);
|
|
340
|
+
warn('Could not find a `dependencies:` block; add `flutter_ota_kit` '
|
|
341
|
+
'manually (run `flutter pub add flutter_ota_kit`).');
|
|
329
342
|
return;
|
|
330
343
|
}
|
|
331
344
|
final insertAt = idx + marker.length;
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
345
|
+
final updated =
|
|
346
|
+
content.replaceRange(insertAt, insertAt, '\n flutter_ota_kit: any\n');
|
|
347
|
+
pubspec.writeAsStringSync(updated);
|
|
348
|
+
step('Added `flutter_ota_kit` dependency to pubspec.yaml '
|
|
349
|
+
'(run `flutter pub get` to resolve the latest version)');
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/// Resolve the `flutter` executable (preferred) or `dart` for `pub add`.
|
|
353
|
+
String? _flutterOrDart() {
|
|
354
|
+
for (final exe in const ['flutter', 'dart']) {
|
|
355
|
+
try {
|
|
356
|
+
final r = Process.runSync(exe, ['--version']);
|
|
357
|
+
if (r.exitCode == 0) return exe;
|
|
358
|
+
} catch (_) {
|
|
359
|
+
// not on PATH; try next
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
return null;
|
|
335
363
|
}
|
|
336
364
|
|
|
337
365
|
void _addInternetPermission() {
|
|
@@ -22,7 +22,7 @@ dependencies:
|
|
|
22
22
|
# merged `flutter_ota_kit` package under lib/src/pkg/. The CLI depends on the
|
|
23
23
|
# single package instead of eight. NOTE: `flutter_ota_kit` is a Flutter plugin,
|
|
24
24
|
# so building the CLI now requires the Flutter SDK (not just the Dart SDK).
|
|
25
|
-
flutter_ota_kit: ^0.2.
|
|
25
|
+
flutter_ota_kit: ^0.2.2
|
|
26
26
|
http: ^1.2.0
|
|
27
27
|
shelf: ^1.4.0
|
|
28
28
|
|