@renbostudios/edge-ota 0.4.0 → 0.4.2
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 +313 -119
- package/dist/index.js +1148 -892
- package/package.json +18 -13
- package/dist/core/crypto.js +0 -87
- package/dist/core/index.js +0 -2
- package/dist/core/manifest.js +0 -108
package/README.md
CHANGED
|
@@ -1,112 +1,211 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://ota.renbo.site/og.png" alt="Edge OTA" width="100%">
|
|
3
|
+
</p>
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
<h1 align="center">
|
|
6
|
+
<code>edge-ota</code>
|
|
7
|
+
</h1>
|
|
4
8
|
|
|
5
|
-
|
|
9
|
+
<p align="center">
|
|
10
|
+
<strong>Zero-SDK, self-hostable OTA update CLI for Expo React Native</strong><br>
|
|
11
|
+
Push signed JavaScript bundles to any EdgeOTA server.
|
|
12
|
+
</p>
|
|
13
|
+
|
|
14
|
+
<p align="center">
|
|
15
|
+
<a href="https://www.npmjs.com/package/@renbostudios/edge-ota"><img src="https://img.shields.io/npm/v/@renbostudios/edge-ota?style=flat-square&color=81C784" alt="npm version"></a>
|
|
16
|
+
<a href="https://github.com/renbostudios/edge-ota-cli/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/@renbostudios/edge-ota?style=flat-square&color=FFAA00" alt="license"></a>
|
|
17
|
+
<a href="https://www.npmjs.com/package/@renbostudios/edge-ota"><img src="https://img.shields.io/npm/dm/@renbostudios/edge-ota?style=flat-square&color=81C784" alt="downloads"></a>
|
|
18
|
+
</p>
|
|
19
|
+
|
|
20
|
+
<p align="center">
|
|
21
|
+
<a href="https://github.com/renbostudios/edge-ota-cli">GitHub</a> · <a href="https://ota.renbo.site">Dashboard</a> · <a href="https://ota.renbo.site/docs">Docs</a> · <a href="https://pd1mvpk7lt.ufs.sh/f/6uDGWrRxa3ipmhByNjc2TlHph0oA4dsWRFUuqZMan18Gwb7g">Video Tutorial</a>
|
|
22
|
+
</p>
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
<br>
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
╔══════════════════════════════════════════════════════════════════╗
|
|
30
|
+
║ ║
|
|
31
|
+
║ ┌─┐┬┌─┬┌┬┐┌─┐┌─┐┬ ┬┌─┐┌┐┌┌┬┐┌─┐ ║
|
|
32
|
+
║ └─┐││ ┤│││├┤ │ ┬├─┤├─┤│││ │ ┤ └─┐ ║
|
|
33
|
+
║ └─┘┴└─┴┴ ┴└ └─┘┴ ┴┴ ┴┘└┘─┴┘└─┘└─┘ ║
|
|
34
|
+
║ ║
|
|
35
|
+
║ Push signed OTA bundles to the edge. ║
|
|
36
|
+
║ Zero SDK. Zero egress. Full control. ║
|
|
37
|
+
║ ║
|
|
38
|
+
╚══════════════════════════════════════════════════════════════════╝
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
<br>
|
|
42
|
+
|
|
43
|
+
## ⚡ Quick Start
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
47
|
+
│ STEP 01 │
|
|
48
|
+
│ Install the CLI globally │
|
|
49
|
+
└──────────────────────────────────────────────────────────────┘
|
|
50
|
+
```
|
|
6
51
|
|
|
7
52
|
```bash
|
|
8
53
|
npm install -g @renbostudios/edge-ota
|
|
9
54
|
```
|
|
10
55
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
56
|
+
```
|
|
57
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
58
|
+
│ STEP 02 │
|
|
59
|
+
│ Log in to your EdgeOTA account │
|
|
60
|
+
└──────────────────────────────────────────────────────────────┘
|
|
61
|
+
```
|
|
14
62
|
|
|
15
63
|
```bash
|
|
16
|
-
# 1. Log in to your EdgeOTA account
|
|
17
64
|
edge-ota login
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
```
|
|
68
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
69
|
+
│ STEP 03 │
|
|
70
|
+
│ Register your project & generate signing keys │
|
|
71
|
+
└──────────────────────────────────────────────────────────────┘
|
|
72
|
+
```
|
|
18
73
|
|
|
19
|
-
|
|
74
|
+
```bash
|
|
20
75
|
edge-ota init
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
80
|
+
│ STEP 04 │
|
|
81
|
+
│ ⚠ REBUILD YOUR NATIVE APP (required!) │
|
|
82
|
+
└──────────────────────────────────────────────────────────────┘
|
|
83
|
+
```
|
|
21
84
|
|
|
22
|
-
|
|
85
|
+
```bash
|
|
23
86
|
npx expo prebuild --clean
|
|
24
87
|
npx expo run:ios
|
|
25
88
|
npx expo run:android
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
93
|
+
│ STEP 05 │
|
|
94
|
+
│ Push an OTA update 🚀 │
|
|
95
|
+
└──────────────────────────────────────────────────────────────┘
|
|
96
|
+
```
|
|
26
97
|
|
|
27
|
-
|
|
98
|
+
```bash
|
|
28
99
|
edge-ota push
|
|
29
100
|
```
|
|
30
101
|
|
|
102
|
+
> **📹 Prefer video?** Watch the full setup tutorial below:
|
|
103
|
+
|
|
104
|
+
<p align="center">
|
|
105
|
+
<video src="https://pd1mvpk7lt.ufs.sh/f/6uDGWrRxa3ipmhByNjc2TlHph0oA4dsWRFUuqZMan18Gwb7g" controls width="100%" style="max-width: 640px; border: 1px solid #333; border-radius: 4px; background: #000;">
|
|
106
|
+
Your browser does not support the video tag.
|
|
107
|
+
</video>
|
|
108
|
+
</p>
|
|
109
|
+
|
|
110
|
+
<br>
|
|
111
|
+
|
|
31
112
|
---
|
|
32
113
|
|
|
33
|
-
|
|
114
|
+
<br>
|
|
115
|
+
|
|
116
|
+
## 📦 Commands
|
|
34
117
|
|
|
35
118
|
### `edge-ota login`
|
|
36
119
|
|
|
37
|
-
Authenticate with your EdgeOTA account. Credentials are stored globally
|
|
120
|
+
Authenticate with your EdgeOTA account. Credentials are stored globally — no per-project `.env` files needed.
|
|
38
121
|
|
|
39
122
|
```bash
|
|
40
|
-
edge-ota login
|
|
41
|
-
edge-ota login --server https://my-server.com
|
|
123
|
+
edge-ota login # default server
|
|
124
|
+
edge-ota login --server https://my-server.com # custom server
|
|
42
125
|
```
|
|
43
126
|
|
|
44
|
-
|
|
127
|
+
```
|
|
128
|
+
┌──────────────────────────────────────────────┐
|
|
129
|
+
│ 📁 Stored at: │
|
|
130
|
+
│ ~/.config/edge-ota/config.json │
|
|
131
|
+
│ │
|
|
132
|
+
│ Contains: auth token, email, server URL │
|
|
133
|
+
└──────────────────────────────────────────────┘
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
---
|
|
45
137
|
|
|
46
138
|
### `edge-ota logout`
|
|
47
139
|
|
|
48
|
-
Remove stored credentials.
|
|
140
|
+
Remove stored credentials from this machine.
|
|
49
141
|
|
|
50
142
|
```bash
|
|
51
143
|
edge-ota logout
|
|
52
144
|
```
|
|
53
145
|
|
|
146
|
+
---
|
|
147
|
+
|
|
54
148
|
### `edge-ota init`
|
|
55
149
|
|
|
56
|
-
|
|
150
|
+
The all-in-one setup command. Registers your project, generates ECDSA P-256 signing keys, and configures `app.json`.
|
|
57
151
|
|
|
58
152
|
```bash
|
|
59
|
-
edge-ota init
|
|
60
|
-
edge-ota init --server https://my-server.com
|
|
153
|
+
edge-ota init # interactive setup
|
|
154
|
+
edge-ota init --server https://my-server.com # override server
|
|
61
155
|
```
|
|
62
156
|
|
|
63
|
-
**What
|
|
157
|
+
**What happens under the hood:**
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
① Fetches your existing projects from the server
|
|
161
|
+
② Lets you select an existing project or create a new one
|
|
162
|
+
③ Generates an ECDSA P-256 key pair
|
|
163
|
+
④ Registers the project with your public key
|
|
164
|
+
⑤ Saves private key → ~/.config/edge-ota/keys/<projectId>.key
|
|
165
|
+
⑥ Updates app.json with server URL, public key, and headers
|
|
166
|
+
```
|
|
64
167
|
|
|
65
|
-
|
|
66
|
-
2. Lets you select an existing project or create a new one
|
|
67
|
-
3. Generates an ECDSA P-256 key pair
|
|
68
|
-
4. Registers the project on the server with your public key
|
|
69
|
-
5. Saves the private key to `~/.config/edge-ota/keys/<projectId>.key`
|
|
70
|
-
6. Updates your `app.json` with:
|
|
71
|
-
- `expo.updates.url` — points to your EdgeOTA server
|
|
72
|
-
- `expo.updates.checkAutomatically` — set to `"ON_LOAD"`
|
|
73
|
-
- `expo.updates.fallbackToCacheTimeout` — set to `30000`
|
|
74
|
-
- `expo.updates.requestHeaders` — sets `expo-channel-name` to `"production"`
|
|
75
|
-
- `expo.extra.edgeOtaServer` — the server URL for manual override
|
|
76
|
-
- `expo.extra.edgeOtaPublicKey` — the generated public key
|
|
168
|
+
> ⚠ **After `init`, you MUST rebuild your native app.** See [Rebuild Required](#-rebuild-required) below.
|
|
77
169
|
|
|
78
|
-
|
|
170
|
+
---
|
|
79
171
|
|
|
80
172
|
### `edge-ota push`
|
|
81
173
|
|
|
82
|
-
Export your Expo bundle and publish an OTA update
|
|
174
|
+
Export your Expo bundle and publish an OTA update.
|
|
83
175
|
|
|
84
176
|
```bash
|
|
85
|
-
edge-ota push
|
|
86
|
-
edge-ota push --channel staging
|
|
87
|
-
edge-ota push --
|
|
88
|
-
edge-ota push --
|
|
89
|
-
edge-ota push --
|
|
90
|
-
edge-ota push --
|
|
177
|
+
edge-ota push # all platforms, production channel
|
|
178
|
+
edge-ota push --channel staging # deploy to staging
|
|
179
|
+
edge-ota push --runtime 1.0.0 # target specific runtime version
|
|
180
|
+
edge-ota push --runtime 1.0.5,1.0.6,1.0.7 # target multiple runtime versions (matrix deployment)
|
|
181
|
+
edge-ota push --platform ios # iOS only
|
|
182
|
+
edge-ota push --platform android # Android only
|
|
183
|
+
edge-ota push --skip-export # use existing ./dist
|
|
184
|
+
edge-ota push --dry-run # build & sign, don't upload
|
|
91
185
|
```
|
|
92
186
|
|
|
93
|
-
**What
|
|
187
|
+
**What happens under the hood:**
|
|
94
188
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
189
|
+
```
|
|
190
|
+
① Runs `npx expo export` to create the JS bundle
|
|
191
|
+
② Collects all assets from ./dist
|
|
192
|
+
③ For each platform (ios/android):
|
|
193
|
+
→ Locates the platform-specific bundle
|
|
194
|
+
→ Signs the payload with your ECDSA private key
|
|
195
|
+
→ Uploads bundle + signature to the server
|
|
196
|
+
④ Server verifies the signature before storing
|
|
197
|
+
```
|
|
102
198
|
|
|
103
199
|
**How it reads your config:**
|
|
104
200
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
201
|
+
| Source | What it reads |
|
|
202
|
+
|---|---|
|
|
203
|
+
| `expo.updates.url` | Server URL + Project ID |
|
|
204
|
+
| `expo.runtimeVersion` | Runtime version (string or policy) |
|
|
205
|
+
| `~/.config/edge-ota/keys/<id>.key` | ECDSA private key |
|
|
206
|
+
| `expo.extra.edgeOtaServer` | Server URL override |
|
|
207
|
+
|
|
208
|
+
---
|
|
110
209
|
|
|
111
210
|
### `edge-ota status`
|
|
112
211
|
|
|
@@ -114,9 +213,11 @@ List recent deployments for the current project.
|
|
|
114
213
|
|
|
115
214
|
```bash
|
|
116
215
|
edge-ota status
|
|
117
|
-
edge-ota status --limit 20
|
|
216
|
+
edge-ota status --limit 20 # show more releases
|
|
118
217
|
```
|
|
119
218
|
|
|
219
|
+
---
|
|
220
|
+
|
|
120
221
|
### `edge-ota keygen`
|
|
121
222
|
|
|
122
223
|
Generate a new ECDSA P-256 key pair and print it to stdout. Does not write any files.
|
|
@@ -127,63 +228,74 @@ edge-ota keygen
|
|
|
127
228
|
|
|
128
229
|
Useful for manual key rotation or generating keys for server-side signing.
|
|
129
230
|
|
|
231
|
+
<br>
|
|
232
|
+
|
|
130
233
|
---
|
|
131
234
|
|
|
132
|
-
|
|
235
|
+
<br>
|
|
133
236
|
|
|
134
|
-
|
|
237
|
+
## 🔄 Rebuild Required
|
|
238
|
+
|
|
239
|
+
After running `edge-ota init`, you **must** rebuild your native app. The `expo-updates` native module reads its config from the **native binary**, not from `app.json` at runtime.
|
|
135
240
|
|
|
136
241
|
```bash
|
|
137
|
-
# Regenerate native projects with fresh config
|
|
138
242
|
npx expo prebuild --clean
|
|
139
|
-
|
|
140
|
-
# Rebuild
|
|
141
243
|
npx expo run:ios
|
|
142
244
|
npx expo run:android
|
|
143
245
|
|
|
144
|
-
#
|
|
246
|
+
# or via EAS
|
|
145
247
|
eas build --profile production
|
|
146
248
|
```
|
|
147
249
|
|
|
148
|
-
**If you skip this step**, the app will fail with:
|
|
149
|
-
|
|
150
250
|
```
|
|
151
|
-
|
|
251
|
+
╔══════════════════════════════════════════════════════════════════╗
|
|
252
|
+
║ ⚠ SKIP THIS STEP AND YOU'LL SEE: ║
|
|
253
|
+
║ ║
|
|
254
|
+
║ "Failed to check for update" ║
|
|
255
|
+
║ ║
|
|
256
|
+
║ The native module has no valid server URL to reach because ║
|
|
257
|
+
║ it was never embedded in the binary. ║
|
|
258
|
+
╚══════════════════════════════════════════════════════════════════╝
|
|
152
259
|
```
|
|
153
260
|
|
|
154
|
-
The native module has no valid server URL to reach because it was never embedded in the binary.
|
|
155
|
-
|
|
156
261
|
You must also rebuild after any change to `expo.updates.url` or `expo.runtimeVersion` in `app.json`.
|
|
157
262
|
|
|
263
|
+
<br>
|
|
264
|
+
|
|
158
265
|
---
|
|
159
266
|
|
|
160
|
-
|
|
267
|
+
<br>
|
|
268
|
+
|
|
269
|
+
## 🔁 How It Works
|
|
161
270
|
|
|
162
271
|
```
|
|
163
|
-
Developer Machine
|
|
164
|
-
─────────────────
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
272
|
+
Developer Machine EdgeOTA Server User's Phone
|
|
273
|
+
───────────────── ────────────── ────────────
|
|
274
|
+
|
|
275
|
+
edge-ota push ──────────────► POST /api/updates
|
|
276
|
+
(ECDSA verified ✓)
|
|
277
|
+
(stores bundle)
|
|
278
|
+
◄──────────── GET /api/updates
|
|
279
|
+
(expo-updates SDK)
|
|
280
|
+
────────────► signed manifest
|
|
281
|
+
◄──────────── GET /api/assets/:hash
|
|
282
|
+
(downloads bundle)
|
|
283
|
+
(reloads app ✓)
|
|
174
284
|
```
|
|
175
285
|
|
|
176
|
-
1. `edge-ota push` runs `expo export` and uploads the Hermes bundle + ECDSA signature
|
|
177
|
-
2. The server verifies the ECDSA P-256 signature before storing anything
|
|
178
|
-
3. When users open the app, `expo-updates` checks
|
|
286
|
+
1. `edge-ota push` runs `expo export` and uploads the Hermes bundle + ECDSA signature
|
|
287
|
+
2. The server **verifies** the ECDSA P-256 signature before storing anything
|
|
288
|
+
3. When users open the app, `expo-updates` checks for a new manifest
|
|
179
289
|
4. The server responds with a signed multipart manifest (Expo Updates Protocol v1)
|
|
180
290
|
5. `expo-updates` downloads and applies the update automatically
|
|
181
291
|
|
|
292
|
+
<br>
|
|
293
|
+
|
|
182
294
|
---
|
|
183
295
|
|
|
184
|
-
|
|
296
|
+
<br>
|
|
185
297
|
|
|
186
|
-
|
|
298
|
+
## ⚙ What `init` Writes to `app.json`
|
|
187
299
|
|
|
188
300
|
```json
|
|
189
301
|
{
|
|
@@ -205,68 +317,99 @@ After running `edge-ota init`, your `app.json` will contain:
|
|
|
205
317
|
}
|
|
206
318
|
```
|
|
207
319
|
|
|
208
|
-
|
|
320
|
+
> `runtimeVersion` is **not modified** by the CLI — it must already exist in your `app.json`. Supports both static strings and policy objects:
|
|
209
321
|
|
|
210
322
|
```json
|
|
211
|
-
// Static (recommended)
|
|
212
323
|
"runtimeVersion": "1.0.0"
|
|
213
|
-
|
|
214
|
-
|
|
324
|
+
```
|
|
325
|
+
```json
|
|
215
326
|
"runtimeVersion": { "policy": "appVersion" }
|
|
216
327
|
```
|
|
217
328
|
|
|
329
|
+
<br>
|
|
330
|
+
|
|
218
331
|
---
|
|
219
332
|
|
|
220
|
-
|
|
333
|
+
<br>
|
|
221
334
|
|
|
222
|
-
|
|
335
|
+
## 🗂 Global Storage
|
|
223
336
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
337
|
+
All credentials and keys are stored **outside** your project directory:
|
|
338
|
+
|
|
339
|
+
```
|
|
340
|
+
~/.config/edge-ota/
|
|
341
|
+
├── config.json ← auth token, email, server URL
|
|
342
|
+
├── keys/
|
|
343
|
+
│ └── <projectId>.key ← ECDSA private key (per-project)
|
|
344
|
+
└── update-check.json ← auto-update check timestamp
|
|
345
|
+
```
|
|
229
346
|
|
|
230
|
-
|
|
347
|
+
```
|
|
348
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
349
|
+
│ 🔒 Nothing sensitive is ever stored in your project repo. │
|
|
350
|
+
└──────────────────────────────────────────────────────────────┘
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
<br>
|
|
231
354
|
|
|
232
355
|
---
|
|
233
356
|
|
|
234
|
-
|
|
357
|
+
<br>
|
|
358
|
+
|
|
359
|
+
## 🧪 Environment Variables
|
|
235
360
|
|
|
236
361
|
| Variable | Purpose |
|
|
237
362
|
|---|---|
|
|
238
|
-
| `EDGE_OTA_TOKEN` | Override the auth token (
|
|
363
|
+
| `EDGE_OTA_TOKEN` | Override the auth token (for CI/CD pipelines) |
|
|
239
364
|
| `EDGE_OTA_UPDATING` | Internal — prevents recursive auto-updates |
|
|
240
365
|
|
|
366
|
+
<br>
|
|
367
|
+
|
|
241
368
|
---
|
|
242
369
|
|
|
243
|
-
|
|
370
|
+
<br>
|
|
371
|
+
|
|
372
|
+
## 🔄 Auto-Update
|
|
244
373
|
|
|
245
|
-
The CLI checks for newer versions on npm every 15 minutes. If a newer version is found, it auto-installs globally. This
|
|
374
|
+
The CLI checks for newer versions on npm every 15 minutes. If a newer version is found, it auto-installs globally. This happens silently in the background and never blocks command execution.
|
|
246
375
|
|
|
247
376
|
To disable: set `EDGE_OTA_UPDATING=true` in your environment.
|
|
248
377
|
|
|
378
|
+
<br>
|
|
379
|
+
|
|
249
380
|
---
|
|
250
381
|
|
|
251
|
-
|
|
382
|
+
<br>
|
|
383
|
+
|
|
384
|
+
## 🔐 Security
|
|
252
385
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
-
|
|
257
|
-
|
|
386
|
+
```
|
|
387
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
388
|
+
│ │
|
|
389
|
+
│ ✅ ECDSA P-256 signing on every bundle upload │
|
|
390
|
+
│ ✅ Server rejects invalid or missing signatures │
|
|
391
|
+
│ ✅ Private keys stored with 0600 permissions │
|
|
392
|
+
│ ✅ Session tokens expire after 24 hours │
|
|
393
|
+
│ ✅ Private keys never leave your machine │
|
|
394
|
+
│ │
|
|
395
|
+
└──────────────────────────────────────────────────────────────┘
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
<br>
|
|
258
399
|
|
|
259
400
|
---
|
|
260
401
|
|
|
261
|
-
|
|
402
|
+
<br>
|
|
403
|
+
|
|
404
|
+
## 🖥 Server Setup
|
|
262
405
|
|
|
263
|
-
The EdgeOTA server is a standard Node.js/Express app.
|
|
406
|
+
The EdgeOTA server is a standard Node.js/Express app. Self-host it or use the managed cloud service at [ota.renbo.site](https://ota.renbo.site).
|
|
264
407
|
|
|
265
408
|
### Docker
|
|
266
409
|
|
|
267
410
|
```bash
|
|
268
|
-
docker pull
|
|
269
|
-
docker run -p 3000:3000 -e DATABASE_URL=...
|
|
411
|
+
docker pull ghcr.io/itskodaaa/edge-ota-backend:latest
|
|
412
|
+
docker run -p 3000:3000 -e DATABASE_URL=... ghcr.io/itskodaaa/edge-ota-backend
|
|
270
413
|
```
|
|
271
414
|
|
|
272
415
|
### Docker Compose
|
|
@@ -286,13 +429,20 @@ pnpm install
|
|
|
286
429
|
pnpm --filter @renbostudios/edge-ota-server-node dev
|
|
287
430
|
```
|
|
288
431
|
|
|
432
|
+
<br>
|
|
433
|
+
|
|
289
434
|
---
|
|
290
435
|
|
|
291
|
-
|
|
436
|
+
<br>
|
|
292
437
|
|
|
293
|
-
|
|
438
|
+
## 🐛 Troubleshooting
|
|
294
439
|
|
|
295
|
-
|
|
440
|
+
<details>
|
|
441
|
+
<summary><strong>"Failed to check for update" on app launch</strong></summary>
|
|
442
|
+
|
|
443
|
+
<br>
|
|
444
|
+
|
|
445
|
+
The `expo-updates` native module can't reach your server because the URL was never embedded in the binary.
|
|
296
446
|
|
|
297
447
|
```bash
|
|
298
448
|
npx expo prebuild --clean
|
|
@@ -300,29 +450,73 @@ npx expo run:ios
|
|
|
300
450
|
npx expo run:android
|
|
301
451
|
```
|
|
302
452
|
|
|
303
|
-
|
|
453
|
+
</details>
|
|
454
|
+
|
|
455
|
+
<details>
|
|
456
|
+
<summary><strong>Updates work on iOS but not Android</strong></summary>
|
|
304
457
|
|
|
305
|
-
|
|
458
|
+
<br>
|
|
459
|
+
|
|
460
|
+
The Android native project may still have the default Expo Updates URL. Regenerate and rebuild:
|
|
306
461
|
|
|
307
462
|
```bash
|
|
308
463
|
npx expo prebuild --clean
|
|
309
464
|
npx expo run:android
|
|
310
465
|
```
|
|
311
466
|
|
|
312
|
-
Verify by checking `android/app/src/main/AndroidManifest.xml` for the `EXPO_UPDATE_URL` meta-data entry
|
|
467
|
+
Verify by checking `android/app/src/main/AndroidManifest.xml` for the `EXPO_UPDATE_URL` meta-data entry.
|
|
468
|
+
|
|
469
|
+
</details>
|
|
470
|
+
|
|
471
|
+
<details>
|
|
472
|
+
<summary><strong>Updates stopped working after a version bump</strong></summary>
|
|
313
473
|
|
|
314
|
-
|
|
474
|
+
<br>
|
|
315
475
|
|
|
316
476
|
If `runtimeVersion` uses the `appVersion` policy, every version bump changes the runtime version. Push a new update after bumping, or switch to a static string.
|
|
317
477
|
|
|
318
|
-
|
|
478
|
+
</details>
|
|
479
|
+
|
|
480
|
+
<details>
|
|
481
|
+
<summary><strong>"No signing key found" error on push</strong></summary>
|
|
482
|
+
|
|
483
|
+
<br>
|
|
319
484
|
|
|
320
485
|
Run `edge-ota init` to generate keys, or use `edge-ota keygen` to generate a new pair and register it manually.
|
|
321
486
|
|
|
487
|
+
</details>
|
|
488
|
+
|
|
489
|
+
<br>
|
|
490
|
+
|
|
491
|
+
---
|
|
492
|
+
|
|
493
|
+
<br>
|
|
494
|
+
|
|
495
|
+
## 📂 Project Structure
|
|
496
|
+
|
|
497
|
+
```
|
|
498
|
+
edge-ota-cli/
|
|
499
|
+
├── apps/
|
|
500
|
+
│ ├── cli/ ← CLI tool (you are here)
|
|
501
|
+
│ ├── server-node/ ← Express + TypeScript API
|
|
502
|
+
│ ├── worker-oss/ ← Cloudflare Worker (open source)
|
|
503
|
+
│ ├── dashboard/ ← SvelteKit frontend
|
|
504
|
+
│ └── core/ ← Shared crypto/manifest logic
|
|
505
|
+
└── packages/
|
|
506
|
+
└── core/ ← @renbostudios/edge-ota-core
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
<br>
|
|
510
|
+
|
|
322
511
|
---
|
|
323
512
|
|
|
324
|
-
|
|
513
|
+
<br>
|
|
325
514
|
|
|
326
|
-
|
|
515
|
+
<p align="center">
|
|
516
|
+
<strong>Built by</strong><br>
|
|
517
|
+
<a href="https://renbostudios.com">Renbo Studios</a> — Mobile App Development Studio
|
|
518
|
+
</p>
|
|
327
519
|
|
|
328
|
-
|
|
520
|
+
<p align="center">
|
|
521
|
+
<sub>MIT License · <code>@renbostudios/edge-ota</code></sub>
|
|
522
|
+
</p>
|