@rubytech/create-maxy 1.0.784 → 1.0.786
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/dist/index.js
CHANGED
|
@@ -1358,6 +1358,19 @@ function buildPlatform() {
|
|
|
1358
1358
|
// server/package.json but NOT shipped as pre-built node_modules — npm pack silently
|
|
1359
1359
|
// strips files from nested node_modules (e.g. rxjs/package.json), breaking require().
|
|
1360
1360
|
// Install fresh on device to guarantee a complete dependency tree.
|
|
1361
|
+
//
|
|
1362
|
+
// On upgrade, wipe `node_modules` first so npm extracts a clean tree. Without
|
|
1363
|
+
// this, an interrupted previous install (network blip, operator cancellation,
|
|
1364
|
+
// power loss) can leave nested package.json files half-truncated — the most
|
|
1365
|
+
// common manifestation is `Error: Invalid package config .../rxjs/package.json`
|
|
1366
|
+
// at server startup, which loops the brand service indefinitely. The wipe
|
|
1367
|
+
// adds ~30 s to upgrades but eliminates a class of unrecoverable customer
|
|
1368
|
+
// states; reliability wins over speed for a one-shot install path.
|
|
1369
|
+
const serverNodeModules = join(INSTALL_DIR, "server", "node_modules");
|
|
1370
|
+
if (existsSync(serverNodeModules)) {
|
|
1371
|
+
console.log(" Wiping previous server/node_modules for a clean reinstall...");
|
|
1372
|
+
rmSync(serverNodeModules, { recursive: true, force: true });
|
|
1373
|
+
}
|
|
1361
1374
|
console.log(` Installing server dependencies (${join(INSTALL_DIR, "server")})...`);
|
|
1362
1375
|
shellRetry("npm", ["install", "--omit=dev", ...NPM_NET_FLAGS], { cwd: join(INSTALL_DIR, "server") }, 3, 15);
|
|
1363
1376
|
}
|
package/package.json
CHANGED
|
@@ -292,12 +292,10 @@ function portalHTML() {
|
|
|
292
292
|
<div class="success-icon">✓</div>
|
|
293
293
|
<h1>Connected!</h1>
|
|
294
294
|
<p class="hint">${escapedBrandName} is now online. Redirecting in <span id="redirect-countdown">15</span>s…</p>
|
|
295
|
-
<
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
<div class="address-box" id="manual-box" style="display:none">
|
|
300
|
-
<span id="device-link-text" style="user-select:all"></span>
|
|
295
|
+
<a id="open-btn" href="#" class="btn" style="text-decoration:none;display:flex;align-items:center;justify-content:center">Open ${escapedBrandName} →</a>
|
|
296
|
+
<p class="hint" style="margin-top:16px">Or copy this URL into your browser:</p>
|
|
297
|
+
<div class="address-box" style="user-select:all" id="manual-box">
|
|
298
|
+
<span id="device-link-text"></span>
|
|
301
299
|
</div>
|
|
302
300
|
<p class="hint">This access point will close shortly.<br>Your phone will reconnect to your WiFi automatically.</p>
|
|
303
301
|
</div>
|
|
@@ -421,21 +419,11 @@ function portalHTML() {
|
|
|
421
419
|
var ipAddr = data.ip ? "http://" + data.ip + devicePort : null;
|
|
422
420
|
// Auto-navigate target: prefer the IP because mDNS .local resolution
|
|
423
421
|
// is flaky on Android (notably Brave) and the redirect dead-ends.
|
|
424
|
-
// The displayed link uses the same URL so what the user sees is what
|
|
425
|
-
// they get if they tap.
|
|
426
422
|
var redirectAddr = ipAddr || hostnameAddr;
|
|
427
|
-
var
|
|
428
|
-
|
|
429
|
-
link.textContent = redirectAddr;
|
|
430
|
-
// Always surface a manual fallback line — captive webviews on some
|
|
431
|
-
// phone OSes silently swallow JS navigation, and the user needs to
|
|
432
|
-
// be able to copy-paste the URL into a real browser.
|
|
423
|
+
var openBtn = document.getElementById("open-btn");
|
|
424
|
+
if (openBtn) openBtn.href = redirectAddr;
|
|
433
425
|
var manualText = document.getElementById("device-link-text");
|
|
434
|
-
if (manualText)
|
|
435
|
-
manualText.textContent = redirectAddr;
|
|
436
|
-
document.getElementById("manual-hint").style.display = "block";
|
|
437
|
-
document.getElementById("manual-box").style.display = "block";
|
|
438
|
-
}
|
|
426
|
+
if (manualText) manualText.textContent = redirectAddr;
|
|
439
427
|
showScreen("success-screen");
|
|
440
428
|
// 15s countdown: the Pi keeps the AP up for ~10s after writing the
|
|
441
429
|
// success result so this poll can land, then tears it down; the
|
|
@@ -40,15 +40,21 @@ PLATFORM_ROOT="${MAXY_PLATFORM_ROOT:-$(dirname "$SCRIPT_DIR")}"
|
|
|
40
40
|
BRAND_JSON="${PLATFORM_ROOT}/config/brand.json"
|
|
41
41
|
CONFIG_DIR=".maxy"
|
|
42
42
|
PRODUCT_NAME="Maxy"
|
|
43
|
-
HOSTNAME_NAME="maxy"
|
|
44
43
|
if [ -f "$BRAND_JSON" ] && command -v jq >/dev/null 2>&1; then
|
|
45
44
|
_dir=$(jq -r '.configDir // empty' "$BRAND_JSON" 2>/dev/null) || true
|
|
46
45
|
[ -n "$_dir" ] && CONFIG_DIR="$_dir"
|
|
47
46
|
_name=$(jq -r '.productName // empty' "$BRAND_JSON" 2>/dev/null) || true
|
|
48
47
|
[ -n "$_name" ] && PRODUCT_NAME="$_name"
|
|
49
|
-
_host=$(jq -r '.hostname // empty' "$BRAND_JSON" 2>/dev/null) || true
|
|
50
|
-
[ -n "$_host" ] && HOSTNAME_NAME="$_host"
|
|
51
48
|
fi
|
|
49
|
+
# HOSTNAME_NAME must be the **actual system hostname** (the name Avahi
|
|
50
|
+
# advertises and the post-connect URL must use), not the brand default
|
|
51
|
+
# from brand.json. The operator's --hostname flag rewrites the system
|
|
52
|
+
# hostname but never touches brand.json's hostname field, so reading
|
|
53
|
+
# from the brand mis-routed the captive portal's success URL to a name
|
|
54
|
+
# that doesn't resolve. `hostname -s` is the canonical answer Avahi
|
|
55
|
+
# itself follows when avahi-daemon.conf has `host-name` left empty,
|
|
56
|
+
# so this is the same source of truth.
|
|
57
|
+
HOSTNAME_NAME="$(hostname -s 2>/dev/null || hostname 2>/dev/null || echo maxy)"
|
|
52
58
|
|
|
53
59
|
# Determine the home directory of the installing user. The service runs as
|
|
54
60
|
# root, but logs and config belong to the user who installed the platform.
|