@renbostudios/edge-ota 0.4.3 → 0.5.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 +6 -6
- package/dist/index.js +68 -5
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<a href="https://ota.renbo.
|
|
2
|
+
<a href="https://ota.renbo.dev">
|
|
3
3
|
<img src="https://raw.githubusercontent.com/renbostudios/edge-ota/main/assets/banner-hero.png" alt="EdgeOTA — Zero-SDK OTA Engine for Expo" width="100%">
|
|
4
4
|
</a>
|
|
5
5
|
</p>
|
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
</p>
|
|
22
22
|
|
|
23
23
|
<p align="center">
|
|
24
|
-
<a href="https://ota.renbo.
|
|
25
|
-
<a href="https://ota.renbo.
|
|
24
|
+
<a href="https://ota.renbo.dev"><strong>Cloud Console</strong></a> ·
|
|
25
|
+
<a href="https://ota.renbo.dev/docs"><strong>Documentation</strong></a> ·
|
|
26
26
|
<a href="#video-walkthrough"><strong>Video Walkthrough</strong></a> ·
|
|
27
27
|
<a href="https://www.npmjs.com/package/@renbostudios/edge-ota"><strong>npm Package</strong></a> ·
|
|
28
28
|
<a href="https://github.com/renbostudios/edge-ota/issues"><strong>Report Issue</strong></a>
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
- **Hardware-Grade Code Signing**: Every Hermes bundle is signed locally using ECDSA P-256 (`prime256v1`). Your private key is stored securely in `~/.config/edge-ota/keys/` and never leaves your machine.
|
|
38
38
|
- **Multi-Runtime Matrix Updates**: Target multiple native app versions simultaneously in a single command (`--runtime 1.0.0,1.0.1,1.0.2`).
|
|
39
39
|
- **100% Protocol v1 Compliant**: Produces standard RFC multipart/mixed manifests and Structured Field Values (`SFV`) signature headers expected by Expo clients.
|
|
40
|
-
- **True Open-Core & Self-Hostable**: Deploy on your own Cloudflare account (`apps/worker-oss`) or Docker VPS (`apps/server-node`), or connect directly to the hosted cloud at [ota.renbo.
|
|
40
|
+
- **True Open-Core & Self-Hostable**: Deploy on your own Cloudflare account (`apps/worker-oss`) or Docker VPS (`apps/server-node`), or connect directly to the hosted cloud at [ota.renbo.dev](https://ota.renbo.dev).
|
|
41
41
|
|
|
42
42
|
---
|
|
43
43
|
|
|
@@ -194,7 +194,7 @@ edge-ota push --skip-export --channel production
|
|
|
194
194
|
{
|
|
195
195
|
"expo": {
|
|
196
196
|
"updates": {
|
|
197
|
-
"url": "https://ota.renbo.
|
|
197
|
+
"url": "https://ota.renbo.dev/api/projects/<projectId>/updates",
|
|
198
198
|
"checkAutomatically": "ON_LOAD",
|
|
199
199
|
"fallbackToCacheTimeout": 30000,
|
|
200
200
|
"requestHeaders": {
|
|
@@ -203,7 +203,7 @@ edge-ota push --skip-export --channel production
|
|
|
203
203
|
},
|
|
204
204
|
"runtimeVersion": "1.0.0",
|
|
205
205
|
"extra": {
|
|
206
|
-
"edgeOtaServer": "https://ota.renbo.
|
|
206
|
+
"edgeOtaServer": "https://ota.renbo.dev",
|
|
207
207
|
"edgeOtaPublicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...\n-----END PUBLIC KEY-----"
|
|
208
208
|
}
|
|
209
209
|
}
|
package/dist/index.js
CHANGED
|
@@ -309,6 +309,50 @@ async function checkAndAutoUpdate() {
|
|
|
309
309
|
} catch {
|
|
310
310
|
}
|
|
311
311
|
}
|
|
312
|
+
var MIGRATION_NOTICE_FILE = path.join(GLOBAL_CONFIG_DIR, "domain-migration-notice.json");
|
|
313
|
+
function getServerHost(serverUrl) {
|
|
314
|
+
try {
|
|
315
|
+
return new URL(serverUrl || DEFAULT_SERVER).host.toLowerCase();
|
|
316
|
+
} catch {
|
|
317
|
+
return "";
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
function isLegacyEdgeOtaHost(serverUrl) {
|
|
321
|
+
const host = getServerHost(serverUrl);
|
|
322
|
+
return host === getServerHost(LEGACY_SERVER) || host.endsWith(".ota.renbo.site");
|
|
323
|
+
}
|
|
324
|
+
function maybeNotifyDomainMigration(serverUrl) {
|
|
325
|
+
try {
|
|
326
|
+
const legacy = isLegacyEdgeOtaHost(serverUrl);
|
|
327
|
+
if (!legacy) {
|
|
328
|
+
const now = Date.now();
|
|
329
|
+
let lastShown = 0;
|
|
330
|
+
try {
|
|
331
|
+
lastShown = JSON.parse(fs.readFileSync(MIGRATION_NOTICE_FILE, "utf-8")).lastShown || 0;
|
|
332
|
+
} catch {
|
|
333
|
+
}
|
|
334
|
+
if (now - lastShown < 24 * 60 * 60 * 1e3) return;
|
|
335
|
+
fs.mkdirSync(GLOBAL_CONFIG_DIR, { recursive: true });
|
|
336
|
+
fs.writeFileSync(MIGRATION_NOTICE_FILE, JSON.stringify({ lastShown: now }));
|
|
337
|
+
}
|
|
338
|
+
const sep = `${c.dim}${"\u2500".repeat(56)}${c.reset}`;
|
|
339
|
+
console.log(`
|
|
340
|
+
${sep}`);
|
|
341
|
+
console.log(` ${c.yellow}\u25B2${c.reset} ${c.bold}EdgeOTA has moved to ${c.green}renbo.dev${c.reset}`);
|
|
342
|
+
if (legacy) {
|
|
343
|
+
console.log(` ${c.dim}saved server:${c.reset} ${c.red}${getServerHost(serverUrl)}${c.reset} ${c.dim}(legacy)${c.reset}`);
|
|
344
|
+
console.log(` ${c.dim}Switch with:${c.reset} ${c.cyan}edge-ota login${c.reset} ${c.dim}(new default: ${DEFAULT_SERVER})${c.reset}`);
|
|
345
|
+
} else {
|
|
346
|
+
console.log(` ${c.dim}dashboard:${c.reset} ${c.cyan}${DASHBOARD_URL}${c.reset}`);
|
|
347
|
+
console.log(` ${c.dim}api:${c.reset} ${c.cyan}${DEFAULT_SERVER}${c.reset}`);
|
|
348
|
+
}
|
|
349
|
+
console.log(` ${c.dim}The legacy API stays online \u2014 existing apps keep receiving updates.${c.reset}`);
|
|
350
|
+
console.log(` ${c.dim}Guide:${c.reset} ${c.cyan}${DASHBOARD_URL}/migration${c.reset}`);
|
|
351
|
+
console.log(`${sep}
|
|
352
|
+
`);
|
|
353
|
+
} catch {
|
|
354
|
+
}
|
|
355
|
+
}
|
|
312
356
|
function printBanner() {
|
|
313
357
|
const sep = `${c.dim}${"\u2500".repeat(56)}${c.reset}`;
|
|
314
358
|
console.log(`
|
|
@@ -319,7 +363,9 @@ ${sep}`);
|
|
|
319
363
|
console.log(`${sep}
|
|
320
364
|
`);
|
|
321
365
|
}
|
|
322
|
-
var DEFAULT_SERVER = "https://api.ota.renbo.
|
|
366
|
+
var DEFAULT_SERVER = "https://api.ota.renbo.dev";
|
|
367
|
+
var LEGACY_SERVER = "https://api.ota.renbo.site";
|
|
368
|
+
var DASHBOARD_URL = "https://ota.renbo.dev";
|
|
323
369
|
function readAppJson(cwd) {
|
|
324
370
|
const appJsonPath = path.resolve(cwd, "app.json");
|
|
325
371
|
if (!fs.existsSync(appJsonPath)) {
|
|
@@ -387,7 +433,7 @@ function readAppJson(cwd) {
|
|
|
387
433
|
"Your app is not configured to receive updates from an EdgeOTA server.",
|
|
388
434
|
[
|
|
389
435
|
`Run ${c.cyan}edge-ota init${c.reset} in this directory to automatically configure your project.`,
|
|
390
|
-
`Or manually add under ${c.dim}"expo.updates"${c.reset}: ${c.cyan}"url": "https://api.ota.renbo.
|
|
436
|
+
`Or manually add under ${c.dim}"expo.updates"${c.reset}: ${c.cyan}"url": "https://api.ota.renbo.dev/api/projects/<project-id>/updates"${c.reset}`
|
|
391
437
|
]
|
|
392
438
|
);
|
|
393
439
|
process.exit(1);
|
|
@@ -645,6 +691,15 @@ function resolveToken() {
|
|
|
645
691
|
return null;
|
|
646
692
|
}
|
|
647
693
|
var program = new Command();
|
|
694
|
+
var migrationNoticeShown = false;
|
|
695
|
+
function notifyDomainMigrationOnce(serverUrl) {
|
|
696
|
+
if (migrationNoticeShown) return;
|
|
697
|
+
migrationNoticeShown = true;
|
|
698
|
+
maybeNotifyDomainMigration(serverUrl);
|
|
699
|
+
}
|
|
700
|
+
program.hook("preAction", () => {
|
|
701
|
+
notifyDomainMigrationOnce(loadGlobalConfig()?.serverUrl);
|
|
702
|
+
});
|
|
648
703
|
program.name("edge-ota").description("Zero-SDK, self-hostable OTA update platform for Expo \u2014 by Renbo Studios").version(packageVersion);
|
|
649
704
|
program.addHelpText("after", `
|
|
650
705
|
${c.bold}Quick Start:${c.reset}
|
|
@@ -654,13 +709,15 @@ ${c.bold}Quick Start:${c.reset}
|
|
|
654
709
|
4. ${c.cyan}edge-ota push${c.reset} Export and publish your first OTA update
|
|
655
710
|
|
|
656
711
|
${c.bold}Documentation & Support:${c.reset}
|
|
657
|
-
Website: https://ota.renbo.
|
|
712
|
+
Website: https://ota.renbo.dev
|
|
713
|
+
Migration: https://ota.renbo.dev/migration ${c.dim}(moved from ota.renbo.site)${c.reset}
|
|
658
714
|
Studio: https://renbostudios.com
|
|
659
715
|
GitHub: https://github.com/renbostudios/edge-ota
|
|
660
716
|
`);
|
|
661
717
|
program.action(() => {
|
|
662
718
|
printBanner();
|
|
663
719
|
const cfg = loadGlobalConfig();
|
|
720
|
+
notifyDomainMigrationOnce(cfg?.serverUrl);
|
|
664
721
|
if (cfg?.email) {
|
|
665
722
|
console.log(` ${c.green}\u25CF${c.reset} Logged in as ${c.bold}${cfg.email}${c.reset} ${c.dim}(${cfg.serverUrl})${c.reset}`);
|
|
666
723
|
} else {
|
|
@@ -719,7 +776,7 @@ ${c.bold}CI/CD Environments:${c.reset}
|
|
|
719
776
|
text || "The credentials provided were rejected by the server.",
|
|
720
777
|
[
|
|
721
778
|
`Check your email and password for typos.`,
|
|
722
|
-
`If you don't have an account yet, register at ${c.bold}https://ota.renbo.
|
|
779
|
+
`If you don't have an account yet, register at ${c.bold}https://ota.renbo.dev${c.reset}`,
|
|
723
780
|
`If using self-hosted server, verify ${c.bold}${serverUrl}${c.reset} is correct.`
|
|
724
781
|
]
|
|
725
782
|
);
|
|
@@ -964,6 +1021,12 @@ ${c.bold}How It Works:${c.reset}
|
|
|
964
1021
|
const appCfg = readAppJson(cwd);
|
|
965
1022
|
const { serverUrl, projectId } = appCfg;
|
|
966
1023
|
const runtimeVersion = options.runtime || appCfg.runtimeVersion;
|
|
1024
|
+
if (isLegacyEdgeOtaHost(serverUrl)) {
|
|
1025
|
+
console.log(` ${c.yellow}\u25B2${c.reset} ${c.dim}app.json still targets the legacy server:${c.reset} ${c.red}${serverUrl}${c.reset}`);
|
|
1026
|
+
console.log(` ${c.dim}This push will work (legacy API stays online), but new installs should use:${c.reset} ${c.cyan}${DEFAULT_SERVER}${c.reset}`);
|
|
1027
|
+
console.log(` ${c.dim}Update ${c.reset}expo.updates.url${c.dim} + ${c.reset}expo.extra.edgeOtaServer${c.dim}, then run ${c.reset}${c.cyan}npx expo prebuild --clean${c.reset}
|
|
1028
|
+
`);
|
|
1029
|
+
}
|
|
967
1030
|
const privateKey = projectId ? loadPrivateKey(projectId) : null;
|
|
968
1031
|
if (!privateKey) {
|
|
969
1032
|
const keyPath = projectId ? path.join(GLOBAL_KEYS_DIR, `${projectId}.key`) : "unknown";
|
|
@@ -1154,7 +1217,7 @@ ${sep}`);
|
|
|
1154
1217
|
printErrorBox(
|
|
1155
1218
|
"Permission denied",
|
|
1156
1219
|
text || `You do not have permission to publish updates to project ${projectId}.`,
|
|
1157
|
-
`Check your team role on ${c.bold}https://ota.renbo.
|
|
1220
|
+
`Check your team role on ${c.bold}https://ota.renbo.dev${c.reset} or verify API key permissions.`
|
|
1158
1221
|
);
|
|
1159
1222
|
} else if (response.status === 404) {
|
|
1160
1223
|
printErrorBox(
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@renbostudios/edge-ota",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"preferGlobal": true,
|
|
5
5
|
"description": "Zero-SDK, self-hostable OTA update CLI for Expo — push signed JS bundles to any EdgeOTA server",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "EdgeOTA Contributors",
|
|
8
|
-
"homepage": "https://ota.renbo.
|
|
8
|
+
"homepage": "https://ota.renbo.dev",
|
|
9
9
|
"publishConfig": {
|
|
10
10
|
"access": "public"
|
|
11
11
|
},
|