@bundle-pilot/capacitor 0.2.4 → 0.3.0
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 +8 -8
- package/dist/index.d.ts +3 -3
- package/dist/index.js +5 -11
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -44,8 +44,9 @@ into it.
|
|
|
44
44
|
- **Rolls back by itself.** A bundle that never starts is rolled back by Capgo,
|
|
45
45
|
and one that fails to bootstrap is reset by `startOta().failed()`. A bundle
|
|
46
46
|
that rolled back is not offered again.
|
|
47
|
-
- **
|
|
48
|
-
|
|
47
|
+
- **Updates before the app goes on.** The first navigation of a session waits
|
|
48
|
+
for the gateway (each request times out after 5 s), so an update installs right away instead of
|
|
49
|
+
at a later tap. Later navigations go on at once.
|
|
49
50
|
- **Knows the native app.** The app's native version goes along with every
|
|
50
51
|
question, so a bundle that needs newer native plugins never reaches an app
|
|
51
52
|
that cannot run it.
|
|
@@ -133,7 +134,7 @@ navigation through. The same code therefore runs in `ng serve` and on the web.
|
|
|
133
134
|
|
|
134
135
|
Upload `4.80.0` to the gateway, and add a rule such as
|
|
135
136
|
`{ "when": { "storeID": ["2020210"] }, "bundle": "4.80.0" }`. Devices of that
|
|
136
|
-
store pick it up at their next
|
|
137
|
+
store pick it up at their next start, while everyone else stays put. To
|
|
137
138
|
widen the rollout, change the rule. To back out, block the bundle in the admin
|
|
138
139
|
UI.
|
|
139
140
|
|
|
@@ -220,10 +221,10 @@ built-in one. Off the native platform it does nothing.
|
|
|
220
221
|
1. **Ask.** The first `check` for a set of facts posts them, along with the
|
|
221
222
|
native app version, to `POST /__gateway/data`. This happens once per
|
|
222
223
|
session, through Capacitor's native HTTP, so CORS does not apply.
|
|
223
|
-
2. **
|
|
224
|
-
bundle, or one that rolled back,
|
|
225
|
-
|
|
226
|
-
navigation.
|
|
224
|
+
2. **Wait for the answer.** That first `check` waits for the gateway. When the
|
|
225
|
+
answer names the running bundle, or one that rolled back, it returns `true`,
|
|
226
|
+
and so does every later `check` for those facts, at once. Otherwise the
|
|
227
|
+
update installs before the navigation goes on.
|
|
227
228
|
3. **Verify.** The pilot fetches `bundle.sha256` and its signature, and checks
|
|
228
229
|
them with WebCrypto Ed25519. An unsigned or tampered bundle is never
|
|
229
230
|
downloaded.
|
|
@@ -241,7 +242,6 @@ current bundle and is not retried until the next start.
|
|
|
241
242
|
|
|
242
243
|
| Key | |
|
|
243
244
|
|---|---|
|
|
244
|
-
| `ota.decision` | the gateway's last answer, so a start never waits on it |
|
|
245
245
|
| `ota.trying` | the bundle being started, to detect a rollback |
|
|
246
246
|
| `ota.failed` | the last bundle that rolled back; it is not offered again |
|
|
247
247
|
| `ota.manifest.<id>` | the digest of the manifest a downloaded bundle came from |
|
package/dist/index.d.ts
CHANGED
|
@@ -15,9 +15,9 @@ export interface OtaOptions {
|
|
|
15
15
|
* A Pilot for native apps: asks the OTA gateway which bundle these facts get, verifies its signed
|
|
16
16
|
* manifest, downloads it with Capgo and reloads into it. Off the native platform it always stays.
|
|
17
17
|
*
|
|
18
|
-
* One question per facts per session.
|
|
19
|
-
*
|
|
20
|
-
*
|
|
18
|
+
* One question per facts per session. The first check() for these facts waits for the answer, so an
|
|
19
|
+
* update installs before the app goes on; once the answer needs no update, check() goes on at once.
|
|
20
|
+
* A failure stays and is not retried that session.
|
|
21
21
|
*/
|
|
22
22
|
export declare function createOtaPilot(o: OtaOptions): Pilot;
|
|
23
23
|
/**
|
package/dist/index.js
CHANGED
|
@@ -5,29 +5,24 @@ import { CapacitorUpdater } from '@capgo/capacitor-updater';
|
|
|
5
5
|
import { entries, verifyManifest } from './manifest.js';
|
|
6
6
|
const TIMEOUT = 5000; // per request
|
|
7
7
|
const DOWNLOAD_TIMEOUT = 60_000;
|
|
8
|
-
//
|
|
8
|
+
// Kept from the app this code came from, so devices in the field keep their state.
|
|
9
9
|
const TRYING = 'ota.trying'; // the bundle set() is about to start
|
|
10
10
|
const FAILED = 'ota.failed'; // a bundle Capgo rolled back: never offered again
|
|
11
11
|
const MANIFEST = 'ota.manifest.'; // + bundle id: digest of the manifest it was downloaded with
|
|
12
|
-
const DECISION = 'ota.decision'; // the gateway's last answer, { key, bundle }, so a start never waits on it
|
|
13
12
|
/**
|
|
14
13
|
* A Pilot for native apps: asks the OTA gateway which bundle these facts get, verifies its signed
|
|
15
14
|
* manifest, downloads it with Capgo and reloads into it. Off the native platform it always stays.
|
|
16
15
|
*
|
|
17
|
-
* One question per facts per session.
|
|
18
|
-
*
|
|
19
|
-
*
|
|
16
|
+
* One question per facts per session. The first check() for these facts waits for the answer, so an
|
|
17
|
+
* update installs before the app goes on; once the answer needs no update, check() goes on at once.
|
|
18
|
+
* A failure stays and is not retried that session.
|
|
20
19
|
*/
|
|
21
20
|
export function createOtaPilot(o) {
|
|
22
21
|
if (!Capacitor.isNativePlatform() || !o.gateway || !o.publicKey)
|
|
23
22
|
return { version: o.version, check: () => true };
|
|
24
23
|
const api = `${o.gateway.replace(/\/+$/, '')}/__gateway`;
|
|
25
24
|
const stays = (v) => !v || v === o.version || v === localStorage.getItem(FAILED);
|
|
26
|
-
let last = null;
|
|
27
|
-
try {
|
|
28
|
-
last = JSON.parse(localStorage.getItem(DECISION) ?? 'null');
|
|
29
|
-
}
|
|
30
|
-
catch { }
|
|
25
|
+
let last = null; // this session's answer
|
|
31
26
|
const asked = new Map();
|
|
32
27
|
let installing;
|
|
33
28
|
const ask = (k, facts) => App.getInfo()
|
|
@@ -43,7 +38,6 @@ export function createOtaPilot(o) {
|
|
|
43
38
|
if (typeof v !== 'string' || !v)
|
|
44
39
|
return null;
|
|
45
40
|
last = { key: k, bundle: v };
|
|
46
|
-
localStorage.setItem(DECISION, JSON.stringify(last));
|
|
47
41
|
return v;
|
|
48
42
|
})
|
|
49
43
|
.catch(() => null);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bundle-pilot/capacitor",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Over-the-air updates for Capacitor apps: install the signed bundle Bundle Pilot picks, with Capgo.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"dist"
|
|
24
24
|
],
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@bundle-pilot/core": "0.
|
|
26
|
+
"@bundle-pilot/core": "0.3.0"
|
|
27
27
|
},
|
|
28
28
|
"peerDependencies": {
|
|
29
29
|
"@capacitor/app": ">=8.0.0",
|