herdr-remote 0.2.3 → 0.2.5
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 +16 -121
- package/README.zh-CN.md +50 -0
- package/bin/herdr-remote.js +14 -15
- package/config.example.json +5 -1
- package/dist/tui.mjs +353 -191
- package/herdr-plugin.toml +6 -6
- package/package.json +4 -3
- package/src/config.js +22 -0
- package/src/exit-codes.js +3 -1
- package/src/host-connector.js +130 -11
- package/src/i18n/en.js +76 -72
- package/src/i18n/zh.js +77 -73
- package/src/service.js +18 -6
- package/src/settings-model.js +44 -1
- package/src/supervisor.js +9 -1
- package/src/updater.js +127 -23
package/dist/tui.mjs
CHANGED
|
@@ -78,6 +78,10 @@ var require_config = __commonJS({
|
|
|
78
78
|
remoteUrl: "",
|
|
79
79
|
maxPayloadBytes: 1024 * 1024,
|
|
80
80
|
maxClientsPerHost: 16,
|
|
81
|
+
maxHosts: 1024,
|
|
82
|
+
maxPendingHandshakes: 1024,
|
|
83
|
+
maxBufferedBytesPerClient: 4 * 1024 * 1024,
|
|
84
|
+
hostReconnectGraceMs: 30 * 1e3,
|
|
81
85
|
allowedOrigins: []
|
|
82
86
|
},
|
|
83
87
|
herdr: {
|
|
@@ -203,6 +207,20 @@ var require_config = __commonJS({
|
|
|
203
207
|
config.relay.port = parseInteger(config.relay.port, DEFAULTS.relay.port, 1, 65535);
|
|
204
208
|
config.relay.maxPayloadBytes = parseInteger(config.relay.maxPayloadBytes, DEFAULTS.relay.maxPayloadBytes, 4096, 16 * 1024 * 1024);
|
|
205
209
|
config.relay.maxClientsPerHost = parseInteger(config.relay.maxClientsPerHost, DEFAULTS.relay.maxClientsPerHost, 1, 256);
|
|
210
|
+
config.relay.maxHosts = parseInteger(config.relay.maxHosts, DEFAULTS.relay.maxHosts, 1, 1e5);
|
|
211
|
+
config.relay.maxPendingHandshakes = parseInteger(config.relay.maxPendingHandshakes, DEFAULTS.relay.maxPendingHandshakes, 16, 1e5);
|
|
212
|
+
config.relay.maxBufferedBytesPerClient = parseInteger(
|
|
213
|
+
config.relay.maxBufferedBytesPerClient,
|
|
214
|
+
DEFAULTS.relay.maxBufferedBytesPerClient,
|
|
215
|
+
64 * 1024,
|
|
216
|
+
256 * 1024 * 1024
|
|
217
|
+
);
|
|
218
|
+
config.relay.hostReconnectGraceMs = parseInteger(
|
|
219
|
+
config.relay.hostReconnectGraceMs,
|
|
220
|
+
DEFAULTS.relay.hostReconnectGraceMs,
|
|
221
|
+
1e3,
|
|
222
|
+
24 * 60 * 60 * 1e3
|
|
223
|
+
);
|
|
206
224
|
config.auth.pairingTtlMs = parseInteger(config.auth.pairingTtlMs, DEFAULTS.auth.pairingTtlMs, 30 * 1e3, 24 * 60 * 60 * 1e3);
|
|
207
225
|
config.auth.deviceTtlMs = parseInteger(config.auth.deviceTtlMs, DEFAULTS.auth.deviceTtlMs, 60 * 1e3, 365 * 24 * 60 * 60 * 1e3);
|
|
208
226
|
config.auth.maxDevices = parseInteger(config.auth.maxDevices, DEFAULTS.auth.maxDevices, 1, 1e4);
|
|
@@ -238,6 +256,10 @@ var require_config = __commonJS({
|
|
|
238
256
|
if (env.RELAY_PORT) config.relay.port = env.RELAY_PORT;
|
|
239
257
|
if (env.RELAY_PUBLIC_URL) config.relay.publicUrl = env.RELAY_PUBLIC_URL;
|
|
240
258
|
if (env.RELAY_REMOTE_URL) config.relay.remoteUrl = env.RELAY_REMOTE_URL;
|
|
259
|
+
if (env.RELAY_MAX_HOSTS) config.relay.maxHosts = env.RELAY_MAX_HOSTS;
|
|
260
|
+
if (env.RELAY_MAX_PENDING_HANDSHAKES) config.relay.maxPendingHandshakes = env.RELAY_MAX_PENDING_HANDSHAKES;
|
|
261
|
+
if (env.RELAY_MAX_BUFFERED_BYTES_PER_CLIENT) config.relay.maxBufferedBytesPerClient = env.RELAY_MAX_BUFFERED_BYTES_PER_CLIENT;
|
|
262
|
+
if (env.RELAY_HOST_RECONNECT_GRACE_MS) config.relay.hostReconnectGraceMs = env.RELAY_HOST_RECONNECT_GRACE_MS;
|
|
241
263
|
if (env.HERDR_SOCKET_PATH) config.herdr.socketPath = env.HERDR_SOCKET_PATH;
|
|
242
264
|
if (env.HERDR_CWD) config.herdr.cwd = env.HERDR_CWD;
|
|
243
265
|
if (env.HERDR_ARGS_JSON) {
|
|
@@ -360,7 +382,7 @@ var require_en = __commonJS({
|
|
|
360
382
|
"use strict";
|
|
361
383
|
module.exports = {
|
|
362
384
|
"app.name": "Herdr Remote",
|
|
363
|
-
"app.tagline": "Remote browser access to
|
|
385
|
+
"app.tagline": "Remote browser access to Herdr workspaces",
|
|
364
386
|
"common.yes": "Yes",
|
|
365
387
|
"common.no": "No",
|
|
366
388
|
"common.on": "on",
|
|
@@ -393,12 +415,12 @@ var require_en = __commonJS({
|
|
|
393
415
|
"nav.about": "Language & about",
|
|
394
416
|
"mode.local": "This machine only",
|
|
395
417
|
"mode.lan": "Local network / Tailscale",
|
|
396
|
-
"mode.official": "Official relay
|
|
418
|
+
"mode.official": "Official relay",
|
|
397
419
|
"mode.remote": "Self-hosted relay",
|
|
398
|
-
"mode.local.description": "
|
|
399
|
-
"mode.lan.description": "
|
|
400
|
-
"mode.official.description": "
|
|
401
|
-
"mode.remote.description": "
|
|
420
|
+
"mode.local.description": "Relay listens on 127.0.0.1. Local browser only.",
|
|
421
|
+
"mode.lan.description": "Relay listens on 0.0.0.0. Accessible over LAN or Tailscale.",
|
|
422
|
+
"mode.official.description": "Connect via official relay. No server needed.",
|
|
423
|
+
"mode.remote.description": "Connect via self-hosted relay for external access.",
|
|
402
424
|
"overview.title": "Status",
|
|
403
425
|
"overview.mode": "Access mode",
|
|
404
426
|
"overview.relay": "Relay",
|
|
@@ -413,20 +435,20 @@ var require_en = __commonJS({
|
|
|
413
435
|
"overview.relayRemote": "remote, {url}",
|
|
414
436
|
"overview.socketMissing": "not found \u2014 is Herdr running?",
|
|
415
437
|
"overview.unreachable": "unreachable: {message}",
|
|
416
|
-
"overview.notStarted": "Services
|
|
438
|
+
"overview.notStarted": "Services not running. Open Services tab to start.",
|
|
417
439
|
"pair.title": "Pair a device",
|
|
418
|
-
"pair.generate": "Generate
|
|
419
|
-
"pair.regenerate": "
|
|
420
|
-
"pair.working": "
|
|
440
|
+
"pair.generate": "Generate pairing code",
|
|
441
|
+
"pair.regenerate": "Regenerate code",
|
|
442
|
+
"pair.working": "Generating pairing code\u2026",
|
|
421
443
|
"pair.code": "Pairing code",
|
|
422
|
-
"pair.url": "
|
|
444
|
+
"pair.url": "Access URL",
|
|
423
445
|
"pair.expires": "Expires in {minutes} (at {time})",
|
|
424
|
-
"pair.expired": "
|
|
425
|
-
"pair.instructions": "Open
|
|
426
|
-
"pair.qrHint": "Scan
|
|
427
|
-
"pair.qrUnavailable": "
|
|
428
|
-
"pair.failed": "Could not create
|
|
429
|
-
"pair.hostOffline": "
|
|
446
|
+
"pair.expired": "Code expired. Generate a new one.",
|
|
447
|
+
"pair.instructions": "Open URL and enter code to pair.",
|
|
448
|
+
"pair.qrHint": "Scan QR code to open URL.",
|
|
449
|
+
"pair.qrUnavailable": "Terminal too narrow for QR code; use URL above.",
|
|
450
|
+
"pair.failed": "Could not create pairing code: {message}",
|
|
451
|
+
"pair.hostOffline": "Relay has no workstation connected. Start services first.",
|
|
430
452
|
"services.title": "Services",
|
|
431
453
|
"services.start": "Start services",
|
|
432
454
|
"services.stop": "Stop services",
|
|
@@ -436,71 +458,74 @@ var require_en = __commonJS({
|
|
|
436
458
|
"services.restarted": "Services restarted.",
|
|
437
459
|
"services.startFailed": "Could not start services: {message}",
|
|
438
460
|
"services.stopFailed": "Could not stop services: {message}",
|
|
439
|
-
"services.unsavedBlocked": "
|
|
440
|
-
"services.managedNotice": "
|
|
441
|
-
"services.logs": "Recent
|
|
442
|
-
"services.logEmpty": "No
|
|
461
|
+
"services.unsavedBlocked": "Unsaved changes. Save before restarting.",
|
|
462
|
+
"services.managedNotice": "Managed by {manager}; applied via keep-alive service.",
|
|
463
|
+
"services.logs": "Recent logs",
|
|
464
|
+
"services.logEmpty": "No logs.",
|
|
443
465
|
"services.logRelay": "Relay",
|
|
444
466
|
"services.logHost": "Host connector",
|
|
445
467
|
"relay.title": "Relay settings",
|
|
446
468
|
"relay.settings": "Settings",
|
|
469
|
+
"relay.locked": "fixed",
|
|
470
|
+
"relay.officialFixed": "The official relay address is fixed and cannot be edited.",
|
|
471
|
+
"relay.officialHint": "Official relay: address is fixed and no password is needed.",
|
|
447
472
|
"relay.password": "Relay password",
|
|
448
|
-
"relay.passwordHint": "Must match RELAY_PASSWORD on
|
|
473
|
+
"relay.passwordHint": "Must match RELAY_PASSWORD on relay. Leave empty if public.",
|
|
449
474
|
"relay.passwordSet": "set",
|
|
450
|
-
"relay.passwordEmpty": "not set (public
|
|
451
|
-
"relay.passwordSaved": "Relay password saved. Restart
|
|
452
|
-
"relay.showPassword": "Show
|
|
453
|
-
"relay.hidePassword": "Hide
|
|
454
|
-
"relay.identity": "Workstation
|
|
455
|
-
"relay.regenerate": "Generate
|
|
456
|
-
"relay.regenerated": "New workstation identity generated. Restart
|
|
457
|
-
"relay.envSnippet": "
|
|
458
|
-
"relay.envHint": "Run this on the relay host.",
|
|
459
|
-
"relay.test": "Test
|
|
475
|
+
"relay.passwordEmpty": "not set (public)",
|
|
476
|
+
"relay.passwordSaved": "Relay password saved. Restart services to apply.",
|
|
477
|
+
"relay.showPassword": "Show password",
|
|
478
|
+
"relay.hidePassword": "Hide password",
|
|
479
|
+
"relay.identity": "Workstation ID",
|
|
480
|
+
"relay.regenerate": "Generate new ID",
|
|
481
|
+
"relay.regenerated": "New workstation identity generated. Restart services to re-register.",
|
|
482
|
+
"relay.envSnippet": "Relay startup command",
|
|
483
|
+
"relay.envHint": "Run this command on the relay host.",
|
|
484
|
+
"relay.test": "Test relay connection",
|
|
460
485
|
"relay.testOk": "Relay reachable: version {version}, {hosts} workstation(s) connected.",
|
|
461
486
|
"relay.testFailed": "Relay unreachable: {message}",
|
|
462
|
-
"relay.selectAddress": "Choose
|
|
487
|
+
"relay.selectAddress": "Choose advertised address",
|
|
463
488
|
"relay.listenAddress": "Listen address",
|
|
464
|
-
"relay.listenAddressHint": "
|
|
489
|
+
"relay.listenAddressHint": "Server bind address. Browsers use advertised address below.",
|
|
465
490
|
"relay.addressTailscale": "Tailscale",
|
|
466
491
|
"relay.addressLan": "LAN",
|
|
467
492
|
"relay.addressVirtual": "virtual",
|
|
468
493
|
"relay.addressLoopback": "loopback",
|
|
469
|
-
"relay.noAddresses": "No non-loopback addresses found.
|
|
470
|
-
"relay.docsHint": "
|
|
494
|
+
"relay.noAddresses": "No non-loopback addresses found.",
|
|
495
|
+
"relay.docsHint": "Self-hosting guide: docs/self-hosted-relay.md",
|
|
471
496
|
"keepalive.title": "Keep-alive service",
|
|
472
497
|
"keepalive.manager": "Manager",
|
|
473
498
|
"keepalive.state": "State",
|
|
474
499
|
"keepalive.install": "Install and start",
|
|
475
500
|
"keepalive.uninstall": "Stop and remove",
|
|
476
|
-
"keepalive.restart": "Restart
|
|
501
|
+
"keepalive.restart": "Restart service",
|
|
477
502
|
"keepalive.installed": "Keep-alive installed with {manager}.",
|
|
478
503
|
"keepalive.uninstalled": "Keep-alive removed.",
|
|
479
504
|
"keepalive.restarted": "Keep-alive service restarted.",
|
|
480
505
|
"keepalive.failed": "Keep-alive operation failed: {message}",
|
|
481
506
|
"keepalive.unitPath": "Unit file",
|
|
482
|
-
"keepalive.logsHint": "
|
|
483
|
-
"keepalive.linger": "Start at boot
|
|
484
|
-
"keepalive.lingerEnabled": "
|
|
485
|
-
"keepalive.lingerDisabled": "
|
|
507
|
+
"keepalive.logsHint": "View logs: {command}",
|
|
508
|
+
"keepalive.linger": "Start at boot",
|
|
509
|
+
"keepalive.lingerEnabled": "Start at boot enabled.",
|
|
510
|
+
"keepalive.lingerDisabled": "Start at boot disabled (runs while logged in).",
|
|
486
511
|
"keepalive.enableLinger": "Enable start at boot",
|
|
487
|
-
"keepalive.lingerDone": "
|
|
488
|
-
"keepalive.fallbackNote": "No system service manager
|
|
512
|
+
"keepalive.lingerDone": "Start at boot enabled for {username}.",
|
|
513
|
+
"keepalive.fallbackNote": "No system service manager found; background process will not survive reboot.",
|
|
489
514
|
"herdr.title": "Herdr integration",
|
|
490
515
|
"herdr.socketPath": "Socket path",
|
|
491
516
|
"herdr.args": "Extra arguments",
|
|
492
517
|
"herdr.plugin": "Plugin registration",
|
|
493
518
|
"herdr.pluginRegistered": "Registered with Herdr.",
|
|
494
519
|
"herdr.pluginMissing": "Not registered with Herdr.",
|
|
495
|
-
"herdr.register": "Register
|
|
496
|
-
"herdr.unregister": "Unregister
|
|
520
|
+
"herdr.register": "Register as Herdr plugin",
|
|
521
|
+
"herdr.unregister": "Unregister plugin",
|
|
497
522
|
"herdr.registerDone": "Registered: {path}",
|
|
498
523
|
"herdr.unregisterDone": "Plugin unregistered.",
|
|
499
524
|
"herdr.registerFailed": "Registration failed: {message}",
|
|
500
|
-
"herdr.cliMissing": "
|
|
525
|
+
"herdr.cliMissing": "Command herdr not found in PATH.",
|
|
501
526
|
"about.title": "Language & about",
|
|
502
527
|
"about.language": "Interface language",
|
|
503
|
-
"about.languageAuto": "Follow
|
|
528
|
+
"about.languageAuto": "Follow system ({detected})",
|
|
504
529
|
"about.languageZh": "\u4E2D\u6587",
|
|
505
530
|
"about.languageEn": "English",
|
|
506
531
|
"about.version": "Version",
|
|
@@ -510,20 +535,20 @@ var require_en = __commonJS({
|
|
|
510
535
|
"about.docs": "Self-hosting guide: docs/self-hosted-relay.md",
|
|
511
536
|
"wizard.title": "First-time setup",
|
|
512
537
|
"wizard.step": "Step {current} of {total}",
|
|
513
|
-
"wizard.languageTitle": "Choose
|
|
514
|
-
"wizard.accessTitle": "
|
|
515
|
-
"wizard.accessHint": "
|
|
516
|
-
"wizard.addressTitle": "
|
|
517
|
-
"wizard.relayTitle": "
|
|
538
|
+
"wizard.languageTitle": "Choose language",
|
|
539
|
+
"wizard.accessTitle": "Access mode",
|
|
540
|
+
"wizard.accessHint": "Can be changed later in Relay settings.",
|
|
541
|
+
"wizard.addressTitle": "Browser access address",
|
|
542
|
+
"wizard.relayTitle": "Relay server",
|
|
518
543
|
"wizard.relayUrlLabel": "Relay URL (wss://\u2026)",
|
|
519
|
-
"wizard.relayHint": "
|
|
544
|
+
"wizard.relayHint": "Relay must be running. See docs/self-hosted-relay.md.",
|
|
520
545
|
"wizard.passwordTitle": "Relay password",
|
|
521
|
-
"wizard.passwordHint": "
|
|
522
|
-
"wizard.finishTitle": "
|
|
546
|
+
"wizard.passwordHint": "RELAY_PASSWORD of the relay. Leave empty if unset.",
|
|
547
|
+
"wizard.finishTitle": "Finish",
|
|
523
548
|
"wizard.finishHint": "Configuration will be saved to {path}.",
|
|
524
|
-
"wizard.startNow": "Start
|
|
525
|
-
"wizard.installKeepalive": "
|
|
526
|
-
"wizard.finish": "Save and
|
|
549
|
+
"wizard.startNow": "Start services now",
|
|
550
|
+
"wizard.installKeepalive": "Run in background",
|
|
551
|
+
"wizard.finish": "Save and finish",
|
|
527
552
|
"field.mode": "Access mode",
|
|
528
553
|
"field.port": "Relay port",
|
|
529
554
|
"field.lanHost": "Browser address",
|
|
@@ -536,15 +561,15 @@ var require_en = __commonJS({
|
|
|
536
561
|
"placeholder.autoDiscovered": "auto-discovered",
|
|
537
562
|
"placeholder.none": "none",
|
|
538
563
|
"error.invalidMode": "Unknown access mode.",
|
|
539
|
-
"error.invalidPort": "
|
|
540
|
-
"error.invalidLanHost": "
|
|
541
|
-
"error.invalidRelayUrl": "
|
|
542
|
-
"error.invalidPublicUrl": "
|
|
564
|
+
"error.invalidPort": "Port must be a number between 1 and 65535.",
|
|
565
|
+
"error.invalidLanHost": "Browser address must be a reachable LAN or Tailscale address, not loopback or 0.0.0.0.",
|
|
566
|
+
"error.invalidRelayUrl": "Relay URL must start with wss://, ws://, https:// or http://.",
|
|
567
|
+
"error.invalidPublicUrl": "Browser URL must start with https:// or http:// and cannot use 0.0.0.0 or ::.",
|
|
543
568
|
"error.invalidLanguage": "Unknown language.",
|
|
544
569
|
"error.invalidKeepalive": "Unknown keep-alive manager.",
|
|
545
570
|
"error.unknownField": "Unknown setting.",
|
|
546
|
-
"error.remoteUrlRequired": "
|
|
547
|
-
"error.saveFailed": "Could not save
|
|
571
|
+
"error.remoteUrlRequired": "Relay URL is required for self-hosted relay mode.",
|
|
572
|
+
"error.saveFailed": "Could not save configuration: {message}",
|
|
548
573
|
"hint.navigate": "\u2191\u2193 move",
|
|
549
574
|
"hint.select": "\u21B5 select",
|
|
550
575
|
"hint.edit": "\u21B5 edit",
|
|
@@ -554,22 +579,23 @@ var require_en = __commonJS({
|
|
|
554
579
|
"hint.mouseOn": "m mouse off",
|
|
555
580
|
"hint.mouseOff": "m mouse on",
|
|
556
581
|
"hint.mouseUnsupported": "mouse unsupported",
|
|
557
|
-
"hint.restartRequired": "Restart
|
|
558
|
-
"hint.unsavedChanges": "Unsaved changes
|
|
582
|
+
"hint.restartRequired": "Restart services to apply changes.",
|
|
583
|
+
"hint.unsavedChanges": "Unsaved changes (press s to save).",
|
|
559
584
|
"hint.save": "s save",
|
|
560
585
|
"hint.editing": "\u21B5 confirm \xB7 esc cancel",
|
|
561
586
|
"update.title": "Updates",
|
|
562
587
|
"update.check": "Check for updates",
|
|
563
588
|
"update.checking": "Checking npm\u2026",
|
|
564
589
|
"update.upToDate": "Up to date ({version})",
|
|
565
|
-
"update.available": "Update
|
|
590
|
+
"update.available": "Update {version} available (press Enter to install)",
|
|
566
591
|
"update.updating": "Installing {version}\u2026",
|
|
567
592
|
"update.done": "Updated to {version}",
|
|
568
|
-
"update.restartHint": "Update installed. Restart herdr-remote to
|
|
569
|
-
"update.errorNetwork": "Could not reach
|
|
570
|
-
"update.
|
|
571
|
-
"update.
|
|
572
|
-
"update.cannot.
|
|
593
|
+
"update.restartHint": "Update installed. Restart herdr-remote to apply.",
|
|
594
|
+
"update.errorNetwork": "Could not reach any npm registry",
|
|
595
|
+
"update.errorNetworkDetail": "No registry answered: {message}",
|
|
596
|
+
"update.errorFailed": "Update failed. Run: npm install -g herdr-remote@latest",
|
|
597
|
+
"update.cannot.source": "Source checkout \u2014 update with git",
|
|
598
|
+
"update.cannot.linked": "Linked package \u2014 managed by npm link"
|
|
573
599
|
};
|
|
574
600
|
}
|
|
575
601
|
});
|
|
@@ -580,7 +606,7 @@ var require_zh = __commonJS({
|
|
|
580
606
|
"use strict";
|
|
581
607
|
module.exports = {
|
|
582
608
|
"app.name": "Herdr Remote",
|
|
583
|
-
"app.tagline": "\u5728\u6D4F\u89C8\u5668\
|
|
609
|
+
"app.tagline": "\u5728\u6D4F\u89C8\u5668\u4E2D\u4F7F\u7528 Herdr \u5DE5\u4F5C\u533A",
|
|
584
610
|
"common.yes": "\u662F",
|
|
585
611
|
"common.no": "\u5426",
|
|
586
612
|
"common.on": "\u5F00",
|
|
@@ -598,11 +624,11 @@ var require_zh = __commonJS({
|
|
|
598
624
|
"common.disabled": "\u5DF2\u505C\u7528",
|
|
599
625
|
"common.loading": "\u5904\u7406\u4E2D\u2026",
|
|
600
626
|
"common.save": "\u4FDD\u5B58\u8BBE\u7F6E",
|
|
601
|
-
"common.saved": "\u914D\u7F6E\u5DF2\u4FDD\u5B58\
|
|
627
|
+
"common.saved": "\u914D\u7F6E\u5DF2\u4FDD\u5B58\u81F3 {path}",
|
|
602
628
|
"common.back": "\u8FD4\u56DE",
|
|
603
629
|
"common.cancel": "\u53D6\u6D88",
|
|
604
630
|
"common.confirm": "\u786E\u8BA4",
|
|
605
|
-
"common.pid": "
|
|
631
|
+
"common.pid": "PID {pid}",
|
|
606
632
|
"common.notApplicable": "\u4E0D\u9002\u7528",
|
|
607
633
|
"nav.overview": "\u6982\u89C8",
|
|
608
634
|
"nav.pair": "\u914D\u5BF9\u8BBE\u5907",
|
|
@@ -613,12 +639,12 @@ var require_zh = __commonJS({
|
|
|
613
639
|
"nav.about": "\u8BED\u8A00\u4E0E\u5173\u4E8E",
|
|
614
640
|
"mode.local": "\u4EC5\u672C\u673A",
|
|
615
641
|
"mode.lan": "\u5C40\u57DF\u7F51 / Tailscale",
|
|
616
|
-
"mode.official": "\u5B98\u65B9
|
|
617
|
-
"mode.remote": "\u81EA\u5EFA
|
|
618
|
-
"mode.local.description": "
|
|
619
|
-
"mode.lan.description": "
|
|
620
|
-
"mode.official.description": "\
|
|
621
|
-
"mode.remote.description": "\
|
|
642
|
+
"mode.official": "\u5B98\u65B9 Relay",
|
|
643
|
+
"mode.remote": "\u81EA\u5EFA Relay",
|
|
644
|
+
"mode.local.description": "\u76D1\u542C 127.0.0.1\uFF0C\u4EC5\u672C\u673A\u53EF\u8BBF\u95EE\u3002",
|
|
645
|
+
"mode.lan.description": "\u76D1\u542C 0.0.0.0\uFF0C\u5C40\u57DF\u7F51\u4E0E Tailscale \u8BBE\u5907\u53EF\u8BBF\u95EE\u3002",
|
|
646
|
+
"mode.official.description": "\u4F7F\u7528\u5B98\u65B9 Relay \u8DE8\u7F51\u8BBF\u95EE\uFF0C\u65E0\u9700\u81EA\u5EFA\u670D\u52A1\u5668\u3002",
|
|
647
|
+
"mode.remote.description": "\u8FDE\u63A5\u81EA\u5EFA Relay \u8DE8\u7F51\u8BBF\u95EE\u3002",
|
|
622
648
|
"overview.title": "\u72B6\u6001",
|
|
623
649
|
"overview.mode": "\u8BBF\u95EE\u65B9\u5F0F",
|
|
624
650
|
"overview.relay": "Relay",
|
|
@@ -628,25 +654,25 @@ var require_zh = __commonJS({
|
|
|
628
654
|
"overview.keepalive": "\u4FDD\u6D3B\u670D\u52A1",
|
|
629
655
|
"overview.devices": "\u6D4F\u89C8\u5668",
|
|
630
656
|
"overview.hosts": "\u5DE5\u4F5C\u7AD9",
|
|
631
|
-
"overview.uptime": "Relay \u8FD0\u884C\u65F6\
|
|
657
|
+
"overview.uptime": "Relay \u8FD0\u884C\u65F6\u95F4",
|
|
632
658
|
"overview.relayLocal": "\u672C\u5730\uFF0C{bind}:{port}",
|
|
633
659
|
"overview.relayRemote": "\u8FDC\u7A0B\uFF0C{url}",
|
|
634
|
-
"overview.socketMissing": "\u672A\u627E\u5230
|
|
660
|
+
"overview.socketMissing": "\u672A\u627E\u5230\uFF0C\u8BF7\u786E\u8BA4 Herdr \u662F\u5426\u8FD0\u884C",
|
|
635
661
|
"overview.unreachable": "\u65E0\u6CD5\u8BBF\u95EE\uFF1A{message}",
|
|
636
|
-
"overview.notStarted": "\u670D\u52A1\u672A\u8FD0\u884C\uFF0C\
|
|
662
|
+
"overview.notStarted": "\u670D\u52A1\u672A\u8FD0\u884C\uFF0C\u53EF\u524D\u5F80\u300C\u670D\u52A1\u300D\u542F\u52A8\u3002",
|
|
637
663
|
"pair.title": "\u914D\u5BF9\u8BBE\u5907",
|
|
638
|
-
"pair.generate": "\u751F\u6210\
|
|
639
|
-
"pair.regenerate": "\u91CD\u65B0\u751F\u6210
|
|
640
|
-
"pair.working": "\
|
|
664
|
+
"pair.generate": "\u751F\u6210\u914D\u5BF9\u7801",
|
|
665
|
+
"pair.regenerate": "\u91CD\u65B0\u751F\u6210",
|
|
666
|
+
"pair.working": "\u751F\u6210\u914D\u5BF9\u7801\u4E2D\u2026",
|
|
641
667
|
"pair.code": "\u914D\u5BF9\u7801",
|
|
642
|
-
"pair.url": "\
|
|
668
|
+
"pair.url": "\u8BBF\u95EE\u5730\u5740",
|
|
643
669
|
"pair.expires": "\u5269\u4F59 {minutes}\uFF08\u81F3 {time}\uFF09",
|
|
644
|
-
"pair.expired": "\u914D\u5BF9\u7801\u5DF2\u8FC7\u671F\uFF0C\
|
|
645
|
-
"pair.instructions": "\u6253\u5F00\u94FE\u63A5\
|
|
646
|
-
"pair.qrHint": "\
|
|
647
|
-
"pair.qrUnavailable": "\u7EC8\u7AEF\u5BBD\u5EA6\u4E0D\u8DB3\
|
|
670
|
+
"pair.expired": "\u914D\u5BF9\u7801\u5DF2\u8FC7\u671F\uFF0C\u9700\u91CD\u65B0\u751F\u6210\u3002",
|
|
671
|
+
"pair.instructions": "\u6253\u5F00\u94FE\u63A5\u5E76\u8F93\u5165\u914D\u5BF9\u7801\u3002",
|
|
672
|
+
"pair.qrHint": "\u626B\u63CF\u4E8C\u7EF4\u7801\u6253\u5F00\u94FE\u63A5\u3002",
|
|
673
|
+
"pair.qrUnavailable": "\u7EC8\u7AEF\u5BBD\u5EA6\u4E0D\u8DB3\uFF0C\u65E0\u6CD5\u663E\u793A\u4E8C\u7EF4\u7801\u3002",
|
|
648
674
|
"pair.failed": "\u751F\u6210\u914D\u5BF9\u7801\u5931\u8D25\uFF1A{message}",
|
|
649
|
-
"pair.hostOffline": "
|
|
675
|
+
"pair.hostOffline": "Relay \u672A\u8FDE\u63A5\u5DE5\u4F5C\u7AD9\uFF0C\u9700\u5148\u542F\u52A8\u670D\u52A1\u3002",
|
|
650
676
|
"services.title": "\u670D\u52A1",
|
|
651
677
|
"services.start": "\u542F\u52A8\u670D\u52A1",
|
|
652
678
|
"services.stop": "\u505C\u6B62\u670D\u52A1",
|
|
@@ -656,38 +682,41 @@ var require_zh = __commonJS({
|
|
|
656
682
|
"services.restarted": "\u670D\u52A1\u5DF2\u91CD\u542F\u3002",
|
|
657
683
|
"services.startFailed": "\u542F\u52A8\u670D\u52A1\u5931\u8D25\uFF1A{message}",
|
|
658
684
|
"services.stopFailed": "\u505C\u6B62\u670D\u52A1\u5931\u8D25\uFF1A{message}",
|
|
659
|
-
"services.unsavedBlocked": "\
|
|
660
|
-
"services.managedNotice": "\
|
|
685
|
+
"services.unsavedBlocked": "\u914D\u7F6E\u672A\u4FDD\u5B58\uFF0C\u8BF7\u5148\u4FDD\u5B58\u518D\u91CD\u542F\u3002",
|
|
686
|
+
"services.managedNotice": "\u7531 {manager} \u6258\u7BA1\uFF0C\u5DF2\u901A\u8FC7\u4FDD\u6D3B\u670D\u52A1\u6267\u884C\u3002",
|
|
661
687
|
"services.logs": "\u6700\u8FD1\u65E5\u5FD7",
|
|
662
|
-
"services.logEmpty": "\u6682\u65E0\u65E5\u5FD7\
|
|
688
|
+
"services.logEmpty": "\u6682\u65E0\u65E5\u5FD7\u3002",
|
|
663
689
|
"services.logRelay": "Relay",
|
|
664
690
|
"services.logHost": "\u4E3B\u673A\u8FDE\u63A5\u5668",
|
|
665
691
|
"relay.title": "Relay \u8BBE\u7F6E",
|
|
666
692
|
"relay.settings": "\u8BBE\u7F6E",
|
|
693
|
+
"relay.locked": "\u56FA\u5B9A",
|
|
694
|
+
"relay.officialFixed": "\u5B98\u65B9 relay \u5730\u5740\u56FA\u5B9A\uFF0C\u4E0D\u53EF\u4FEE\u6539\u3002",
|
|
695
|
+
"relay.officialHint": "\u5B98\u65B9 relay\uFF1A\u5730\u5740\u56FA\u5B9A\uFF0C\u65E0\u9700\u5BC6\u7801\u3002",
|
|
667
696
|
"relay.password": "Relay \u5BC6\u7801",
|
|
668
|
-
"relay.passwordHint": "\
|
|
697
|
+
"relay.passwordHint": "\u987B\u4E0E Relay \u7AEF\u7684 RELAY_PASSWORD \u4E00\u81F4\u3002\u7559\u7A7A\u4E3A\u516C\u7528 Relay\u3002",
|
|
669
698
|
"relay.passwordSet": "\u5DF2\u8BBE\u7F6E",
|
|
670
|
-
"relay.passwordEmpty": "\u672A\u8BBE\u7F6E\uFF08\u516C\u7528
|
|
671
|
-
"relay.passwordSaved": "Relay \u5BC6\u7801\u5DF2\u4FDD\u5B58\uFF0C\u91CD\u542F\u670D\u52A1\
|
|
699
|
+
"relay.passwordEmpty": "\u672A\u8BBE\u7F6E\uFF08\u516C\u7528\uFF09",
|
|
700
|
+
"relay.passwordSaved": "Relay \u5BC6\u7801\u5DF2\u4FDD\u5B58\uFF0C\u91CD\u542F\u670D\u52A1\u751F\u6548\u3002",
|
|
672
701
|
"relay.showPassword": "\u663E\u793A\u5BC6\u7801",
|
|
673
702
|
"relay.hidePassword": "\u9690\u85CF\u5BC6\u7801",
|
|
674
703
|
"relay.identity": "\u5DE5\u4F5C\u7AD9\u6807\u8BC6",
|
|
675
|
-
"relay.regenerate": "\u91CD\u65B0\u751F\u6210\
|
|
676
|
-
"relay.regenerated": "\u5DF2\u751F\u6210\u65B0\
|
|
677
|
-
"relay.envSnippet": "
|
|
678
|
-
"relay.envHint": "\u5728
|
|
679
|
-
"relay.test": "\u6D4B\u8BD5
|
|
680
|
-
"relay.testOk": "
|
|
681
|
-
"relay.testFailed": "
|
|
682
|
-
"relay.selectAddress": "\u9009\u62E9\
|
|
704
|
+
"relay.regenerate": "\u91CD\u65B0\u751F\u6210\u6807\u8BC6",
|
|
705
|
+
"relay.regenerated": "\u5DF2\u751F\u6210\u65B0\u6807\u8BC6\uFF0C\u91CD\u542F\u540E\u91CD\u65B0\u6CE8\u518C\u3002",
|
|
706
|
+
"relay.envSnippet": "Relay \u542F\u52A8\u547D\u4EE4",
|
|
707
|
+
"relay.envHint": "\u5728 Relay \u4E3B\u673A\u6267\u884C\u6B64\u547D\u4EE4\u3002",
|
|
708
|
+
"relay.test": "\u6D4B\u8BD5 Relay \u8FDE\u63A5",
|
|
709
|
+
"relay.testOk": "Relay \u53EF\u8BBF\u95EE\uFF1A\u7248\u672C {version}\uFF0C\u5DF2\u8FDE\u63A5 {hosts} \u53F0\u5DE5\u4F5C\u7AD9\u3002",
|
|
710
|
+
"relay.testFailed": "Relay \u65E0\u6CD5\u8BBF\u95EE\uFF1A{message}",
|
|
711
|
+
"relay.selectAddress": "\u9009\u62E9\u516C\u5E03\u5730\u5740",
|
|
683
712
|
"relay.listenAddress": "\u76D1\u542C\u5730\u5740",
|
|
684
|
-
"relay.listenAddressHint": "\
|
|
713
|
+
"relay.listenAddressHint": "\u670D\u52A1\u5668\u7ED1\u5B9A\u5730\u5740\uFF1B\u6D4F\u89C8\u5668\u8BBF\u95EE\u4E0B\u65B9\u516C\u5E03\u5730\u5740\u3002",
|
|
685
714
|
"relay.addressTailscale": "Tailscale",
|
|
686
715
|
"relay.addressLan": "\u5C40\u57DF\u7F51",
|
|
687
716
|
"relay.addressVirtual": "\u865A\u62DF\u7F51\u5361",
|
|
688
717
|
"relay.addressLoopback": "\u56DE\u73AF",
|
|
689
|
-
"relay.noAddresses": "\
|
|
690
|
-
"relay.docsHint": "\u81EA\u5EFA
|
|
718
|
+
"relay.noAddresses": "\u672A\u627E\u5230\u975E\u56DE\u73AF\u5730\u5740\u3002",
|
|
719
|
+
"relay.docsHint": "\u81EA\u5EFA\u6307\u5357\uFF1Adocs/self-hosted-relay.zh-CN.md",
|
|
691
720
|
"keepalive.title": "\u540E\u53F0\u4FDD\u6D3B\u670D\u52A1",
|
|
692
721
|
"keepalive.manager": "\u7BA1\u7406\u65B9\u5F0F",
|
|
693
722
|
"keepalive.state": "\u72B6\u6001",
|
|
@@ -700,24 +729,24 @@ var require_zh = __commonJS({
|
|
|
700
729
|
"keepalive.failed": "\u4FDD\u6D3B\u64CD\u4F5C\u5931\u8D25\uFF1A{message}",
|
|
701
730
|
"keepalive.unitPath": "\u5355\u5143\u6587\u4EF6",
|
|
702
731
|
"keepalive.logsHint": "\u67E5\u770B\u65E5\u5FD7\uFF1A{command}",
|
|
703
|
-
"keepalive.linger": "\
|
|
704
|
-
"keepalive.lingerEnabled": "\u5DF2\u5F00\u542F
|
|
705
|
-
"keepalive.lingerDisabled": "\u672A\u5F00\u542F
|
|
732
|
+
"keepalive.linger": "\u5F00\u673A\u81EA\u542F",
|
|
733
|
+
"keepalive.lingerEnabled": "\u5DF2\u5F00\u542F\u5F00\u673A\u81EA\u542F\u3002",
|
|
734
|
+
"keepalive.lingerDisabled": "\u672A\u5F00\u542F\u5F00\u673A\u81EA\u542F\uFF08\u4EC5\u767B\u5F55\u671F\u95F4\u8FD0\u884C\uFF09\u3002",
|
|
706
735
|
"keepalive.enableLinger": "\u5F00\u542F\u5F00\u673A\u81EA\u542F",
|
|
707
|
-
"keepalive.lingerDone": "\u5DF2\u4E3A {username} \u5F00\u542F
|
|
708
|
-
"keepalive.fallbackNote": "\u7CFB\u7EDF\
|
|
736
|
+
"keepalive.lingerDone": "\u5DF2\u4E3A {username} \u5F00\u542F\u5F00\u673A\u81EA\u542F\u3002",
|
|
737
|
+
"keepalive.fallbackNote": "\u65E0\u7CFB\u7EDF\u670D\u52A1\u7BA1\u7406\u5668\uFF0C\u4F7F\u7528\u540E\u53F0\u5B88\u62A4\u8FDB\u7A0B\uFF0C\u91CD\u542F\u540E\u4E0D\u81EA\u52A8\u6062\u590D\u3002",
|
|
709
738
|
"herdr.title": "Herdr \u96C6\u6210",
|
|
710
739
|
"herdr.socketPath": "\u5957\u63A5\u5B57\u8DEF\u5F84",
|
|
711
740
|
"herdr.args": "\u9644\u52A0\u53C2\u6570",
|
|
712
741
|
"herdr.plugin": "\u63D2\u4EF6\u6CE8\u518C",
|
|
713
742
|
"herdr.pluginRegistered": "\u5DF2\u6CE8\u518C\u5230 Herdr\u3002",
|
|
714
743
|
"herdr.pluginMissing": "\u5C1A\u672A\u6CE8\u518C\u5230 Herdr\u3002",
|
|
715
|
-
"herdr.register": "\
|
|
716
|
-
"herdr.unregister": "\u53D6\u6D88\u6CE8\u518C
|
|
744
|
+
"herdr.register": "\u6CE8\u518C\u4E3A Herdr \u63D2\u4EF6",
|
|
745
|
+
"herdr.unregister": "\u53D6\u6D88\u6CE8\u518C",
|
|
717
746
|
"herdr.registerDone": "\u5DF2\u6CE8\u518C\uFF1A{path}",
|
|
718
|
-
"herdr.unregisterDone": "\
|
|
747
|
+
"herdr.unregisterDone": "\u5DF2\u53D6\u6D88\u6CE8\u518C\u3002",
|
|
719
748
|
"herdr.registerFailed": "\u6CE8\u518C\u5931\u8D25\uFF1A{message}",
|
|
720
|
-
"herdr.cliMissing": "PATH \u4E2D\u627E\
|
|
749
|
+
"herdr.cliMissing": "PATH \u4E2D\u672A\u627E\u5230 herdr \u547D\u4EE4\u3002",
|
|
721
750
|
"about.title": "\u8BED\u8A00\u4E0E\u5173\u4E8E",
|
|
722
751
|
"about.language": "\u754C\u9762\u8BED\u8A00",
|
|
723
752
|
"about.languageAuto": "\u8DDF\u968F\u7CFB\u7EDF\uFF08{detected}\uFF09",
|
|
@@ -727,23 +756,23 @@ var require_zh = __commonJS({
|
|
|
727
756
|
"about.configPath": "\u914D\u7F6E\u6587\u4EF6",
|
|
728
757
|
"about.statePath": "\u72B6\u6001\u76EE\u5F55",
|
|
729
758
|
"about.relayPackage": "Relay \u5305",
|
|
730
|
-
"about.docs": "\u81EA\u5EFA
|
|
759
|
+
"about.docs": "\u81EA\u5EFA\u6307\u5357\uFF1Adocs/self-hosted-relay.zh-CN.md",
|
|
731
760
|
"wizard.title": "\u9996\u6B21\u8BBE\u7F6E",
|
|
732
761
|
"wizard.step": "\u7B2C {current} / {total} \u6B65",
|
|
733
762
|
"wizard.languageTitle": "\u9009\u62E9\u8BED\u8A00",
|
|
734
|
-
"wizard.accessTitle": "\
|
|
735
|
-
"wizard.accessHint": "\
|
|
736
|
-
"wizard.addressTitle": "\
|
|
737
|
-
"wizard.relayTitle": "
|
|
763
|
+
"wizard.accessTitle": "\u9009\u62E9\u8BBF\u95EE\u65B9\u5F0F",
|
|
764
|
+
"wizard.accessHint": "\u540E\u7EED\u53EF\u5728 Relay \u9875\u9762\u4FEE\u6539\u3002",
|
|
765
|
+
"wizard.addressTitle": "\u9009\u62E9\u8BBF\u95EE\u5730\u5740",
|
|
766
|
+
"wizard.relayTitle": "Relay \u670D\u52A1\u5668",
|
|
738
767
|
"wizard.relayUrlLabel": "Relay \u5730\u5740\uFF08wss://\u2026\uFF09",
|
|
739
|
-
"wizard.relayHint": "
|
|
768
|
+
"wizard.relayHint": "Relay \u9700\u5148\u8FD0\u884C\u3002\u642D\u5EFA\u6307\u5357\u89C1 docs/self-hosted-relay.zh-CN.md\u3002",
|
|
740
769
|
"wizard.passwordTitle": "Relay \u5BC6\u7801",
|
|
741
|
-
"wizard.passwordHint": "
|
|
770
|
+
"wizard.passwordHint": "Relay \u7684 RELAY_PASSWORD\u3002\u672A\u8BBE\u7559\u7A7A\u3002",
|
|
742
771
|
"wizard.finishTitle": "\u5B8C\u6210",
|
|
743
|
-
"wizard.finishHint": "\u914D\u7F6E\u5C06\u4FDD\u5B58\
|
|
772
|
+
"wizard.finishHint": "\u914D\u7F6E\u5C06\u4FDD\u5B58\u81F3 {path}\u3002",
|
|
744
773
|
"wizard.startNow": "\u7ACB\u5373\u542F\u52A8\u670D\u52A1",
|
|
745
|
-
"wizard.installKeepalive": "\
|
|
746
|
-
"wizard.finish": "\u4FDD\u5B58\u5E76\
|
|
774
|
+
"wizard.installKeepalive": "\u540E\u53F0\u4FDD\u6D3B",
|
|
775
|
+
"wizard.finish": "\u4FDD\u5B58\u5E76\u5B8C\u6210",
|
|
747
776
|
"field.mode": "\u8BBF\u95EE\u65B9\u5F0F",
|
|
748
777
|
"field.port": "Relay \u7AEF\u53E3",
|
|
749
778
|
"field.lanHost": "\u6D4F\u89C8\u5668\u5730\u5740",
|
|
@@ -756,14 +785,14 @@ var require_zh = __commonJS({
|
|
|
756
785
|
"placeholder.autoDiscovered": "\u81EA\u52A8\u63A2\u6D4B",
|
|
757
786
|
"placeholder.none": "\u65E0",
|
|
758
787
|
"error.invalidMode": "\u672A\u77E5\u7684\u8BBF\u95EE\u65B9\u5F0F\u3002",
|
|
759
|
-
"error.invalidPort": "\u7AEF\u53E3\
|
|
760
|
-
"error.invalidLanHost": "\u6D4F\u89C8\u5668\u5730\u5740\
|
|
761
|
-
"error.invalidRelayUrl": "Relay \u5730\u5740\
|
|
762
|
-
"error.invalidPublicUrl": "\u6D4F\u89C8\u5668\u5730\u5740\
|
|
788
|
+
"error.invalidPort": "\u7AEF\u53E3\u987B\u4E3A 1 \u5230 65535 \u4E4B\u95F4\u7684\u6570\u5B57\u3002",
|
|
789
|
+
"error.invalidLanHost": "\u6D4F\u89C8\u5668\u5730\u5740\u987B\u4E3A\u53EF\u8BBF\u95EE\u5C40\u57DF\u7F51\u6216 Tailscale \u5730\u5740\uFF0C\u4E0D\u80FD\u4E3A\u56DE\u73AF\u6216 0.0.0.0\u3002",
|
|
790
|
+
"error.invalidRelayUrl": "Relay \u5730\u5740\u987B\u4EE5 wss://\u3001ws://\u3001https:// \u6216 http:// \u5F00\u5934\u3002",
|
|
791
|
+
"error.invalidPublicUrl": "\u6D4F\u89C8\u5668\u5730\u5740\u987B\u4EE5 https:// \u6216 http:// \u5F00\u5934\uFF0C\u4E0D\u80FD\u4E3A 0.0.0.0 \u6216 ::\u3002",
|
|
763
792
|
"error.invalidLanguage": "\u672A\u77E5\u7684\u8BED\u8A00\u3002",
|
|
764
793
|
"error.invalidKeepalive": "\u672A\u77E5\u7684\u4FDD\u6D3B\u7BA1\u7406\u65B9\u5F0F\u3002",
|
|
765
794
|
"error.unknownField": "\u672A\u77E5\u7684\u8BBE\u7F6E\u9879\u3002",
|
|
766
|
-
"error.remoteUrlRequired": "\u81EA\u5EFA
|
|
795
|
+
"error.remoteUrlRequired": "\u81EA\u5EFA Relay \u6A21\u5F0F\u987B\u586B\u5199 Relay \u5730\u5740\u3002",
|
|
767
796
|
"error.saveFailed": "\u4FDD\u5B58\u914D\u7F6E\u5931\u8D25\uFF1A{message}",
|
|
768
797
|
"hint.navigate": "\u2191\u2193 \u79FB\u52A8",
|
|
769
798
|
"hint.select": "\u21B5 \u9009\u62E9",
|
|
@@ -774,22 +803,23 @@ var require_zh = __commonJS({
|
|
|
774
803
|
"hint.mouseOn": "m \u5173\u95ED\u9F20\u6807",
|
|
775
804
|
"hint.mouseOff": "m \u5F00\u542F\u9F20\u6807",
|
|
776
805
|
"hint.mouseUnsupported": "\u4E0D\u652F\u6301\u9F20\u6807",
|
|
777
|
-
"hint.restartRequired": "\
|
|
778
|
-
"hint.unsavedChanges": "\u6709\u672A\u4FDD\u5B58\
|
|
806
|
+
"hint.restartRequired": "\u91CD\u542F\u670D\u52A1\u751F\u6548\u3002",
|
|
807
|
+
"hint.unsavedChanges": "\u6709\u672A\u4FDD\u5B58\u4FEE\u6539\uFF08\u6309 s \u4FDD\u5B58\uFF09\u3002",
|
|
779
808
|
"hint.save": "s \u4FDD\u5B58",
|
|
780
809
|
"hint.editing": "\u21B5 \u786E\u8BA4 \xB7 esc \u53D6\u6D88",
|
|
781
810
|
"update.title": "\u66F4\u65B0",
|
|
782
811
|
"update.check": "\u68C0\u67E5\u66F4\u65B0",
|
|
783
|
-
"update.checking": "\
|
|
812
|
+
"update.checking": "\u67E5\u8BE2 npm \u4E2D\u2026",
|
|
784
813
|
"update.upToDate": "\u5DF2\u662F\u6700\u65B0\uFF08{version}\uFF09",
|
|
785
|
-
"update.available": "\
|
|
786
|
-
"update.updating": "\
|
|
787
|
-
"update.done": "\u5DF2\u66F4\u65B0\
|
|
788
|
-
"update.restartHint": "\u66F4\u65B0\u5DF2\u5B89\u88C5\uFF0C\u91CD\u542F herdr-remote \
|
|
789
|
-
"update.errorNetwork": "\u65E0\u6CD5\u8FDE\u63A5
|
|
814
|
+
"update.available": "\u65B0\u7248\u672C {version} \u53EF\u7528\uFF08\u6309 Enter \u5B89\u88C5\uFF09",
|
|
815
|
+
"update.updating": "\u5B89\u88C5 {version} \u4E2D\u2026",
|
|
816
|
+
"update.done": "\u5DF2\u66F4\u65B0\u81F3 {version}",
|
|
817
|
+
"update.restartHint": "\u66F4\u65B0\u5DF2\u5B89\u88C5\uFF0C\u91CD\u542F herdr-remote \u751F\u6548\u3002",
|
|
818
|
+
"update.errorNetwork": "\u6240\u6709 npm registry \u5747\u65E0\u6CD5\u8FDE\u63A5",
|
|
819
|
+
"update.errorNetworkDetail": "\u65E0 registry \u5E94\u7B54\uFF1A{message}",
|
|
790
820
|
"update.errorFailed": "\u66F4\u65B0\u5931\u8D25\uFF0C\u53EF\u624B\u52A8\u6267\u884C\uFF1Anpm install -g herdr-remote@latest",
|
|
791
|
-
"update.cannot.source": "\
|
|
792
|
-
"update.cannot.linked": "
|
|
821
|
+
"update.cannot.source": "\u6E90\u7801\u76EE\u5F55\u8FD0\u884C\uFF0C\u8BF7\u4F7F\u7528 git \u66F4\u65B0",
|
|
822
|
+
"update.cannot.linked": "npm link \u5DE5\u4F5C\u526F\u672C\uFF0C\u7531 npm link \u7BA1\u7406"
|
|
793
823
|
};
|
|
794
824
|
}
|
|
795
825
|
});
|
|
@@ -954,6 +984,7 @@ var require_settings_model = __commonJS({
|
|
|
954
984
|
ACCESS_MODES: ACCESS_MODES2,
|
|
955
985
|
KEEPALIVE_MANAGERS,
|
|
956
986
|
LANGUAGES,
|
|
987
|
+
OFFICIAL_RELAY_URL: OFFICIAL_RELAY_URL2,
|
|
957
988
|
configDir,
|
|
958
989
|
configPath: configPath2,
|
|
959
990
|
isLoopbackHost,
|
|
@@ -976,6 +1007,14 @@ var require_settings_model = __commonJS({
|
|
|
976
1007
|
{ id: "keepaliveManager", kind: "choice", choices: KEEPALIVE_MANAGERS, labelKey: "field.keepalive" }
|
|
977
1008
|
];
|
|
978
1009
|
var EMPTY = "";
|
|
1010
|
+
var SELECTABLE_MODES2 = ["local", "lan", "official", "remote"];
|
|
1011
|
+
function selectedMode2(draft) {
|
|
1012
|
+
if (draft.relay.mode === "remote" && draft.relay.remoteUrl === OFFICIAL_RELAY_URL2) return "official";
|
|
1013
|
+
return draft.relay.mode;
|
|
1014
|
+
}
|
|
1015
|
+
function isOfficialRelay2(draft) {
|
|
1016
|
+
return selectedMode2(draft) === "official";
|
|
1017
|
+
}
|
|
979
1018
|
function clone(value) {
|
|
980
1019
|
return JSON.parse(JSON.stringify(value));
|
|
981
1020
|
}
|
|
@@ -1038,7 +1077,16 @@ var require_settings_model = __commonJS({
|
|
|
1038
1077
|
const value = typeof rawValue === "string" ? rawValue.trim() : rawValue;
|
|
1039
1078
|
switch (id) {
|
|
1040
1079
|
case "mode": {
|
|
1041
|
-
if (!
|
|
1080
|
+
if (!SELECTABLE_MODES2.includes(value)) return { draft, errorKey: "error.invalidMode" };
|
|
1081
|
+
if (value === "official") {
|
|
1082
|
+
next.relay.mode = "remote";
|
|
1083
|
+
next.relay.remoteUrl = OFFICIAL_RELAY_URL2;
|
|
1084
|
+
next.relay.publicUrl = EMPTY;
|
|
1085
|
+
break;
|
|
1086
|
+
}
|
|
1087
|
+
if (value === "remote" && next.relay.remoteUrl === OFFICIAL_RELAY_URL2) {
|
|
1088
|
+
next.relay.remoteUrl = EMPTY;
|
|
1089
|
+
}
|
|
1042
1090
|
next.relay.mode = value;
|
|
1043
1091
|
if (value === "lan" && (isLoopbackHost(next.relay.lanHost) || isUnspecifiedAddress(next.relay.lanHost))) {
|
|
1044
1092
|
next.relay.lanHost = EMPTY;
|
|
@@ -1139,8 +1187,11 @@ var require_settings_model = __commonJS({
|
|
|
1139
1187
|
}
|
|
1140
1188
|
module.exports = {
|
|
1141
1189
|
FIELDS: FIELDS2,
|
|
1190
|
+
SELECTABLE_MODES: SELECTABLE_MODES2,
|
|
1142
1191
|
createDraft: createDraft2,
|
|
1143
1192
|
fieldsForMode: fieldsForMode2,
|
|
1193
|
+
isOfficialRelay: isOfficialRelay2,
|
|
1194
|
+
selectedMode: selectedMode2,
|
|
1144
1195
|
getField: getField2,
|
|
1145
1196
|
getFieldPlaceholder: getFieldPlaceholder2,
|
|
1146
1197
|
setField: setField2,
|
|
@@ -1521,7 +1572,11 @@ var require_service = __commonJS({
|
|
|
1521
1572
|
RELAY_PASSWORD: state.hostToken,
|
|
1522
1573
|
RELAY_AUTH_STATE_FILE: relayAuthStatePath(),
|
|
1523
1574
|
RELAY_ALLOWED_ORIGINS: (config.relay.allowedOrigins || []).join(","),
|
|
1524
|
-
RELAY_MAX_CLIENTS_PER_HOST: String(config.relay.maxClientsPerHost)
|
|
1575
|
+
RELAY_MAX_CLIENTS_PER_HOST: String(config.relay.maxClientsPerHost),
|
|
1576
|
+
RELAY_MAX_HOSTS: String(config.relay.maxHosts),
|
|
1577
|
+
RELAY_MAX_PENDING_HANDSHAKES: String(config.relay.maxPendingHandshakes),
|
|
1578
|
+
RELAY_MAX_BUFFERED_BYTES_PER_CLIENT: String(config.relay.maxBufferedBytesPerClient),
|
|
1579
|
+
RELAY_HOST_RECONNECT_GRACE_MS: String(config.relay.hostReconnectGraceMs)
|
|
1525
1580
|
}
|
|
1526
1581
|
});
|
|
1527
1582
|
}
|
|
@@ -1704,18 +1759,26 @@ var require_service = __commonJS({
|
|
|
1704
1759
|
throw lastError || new Error("relay did not become ready");
|
|
1705
1760
|
}
|
|
1706
1761
|
async function waitForHost(config, { attempts = 30, delayMs = 100 } = {}) {
|
|
1707
|
-
|
|
1762
|
+
const state = ensureRuntime2();
|
|
1763
|
+
const statusEndpoint = `${resolveAdminOrigin2(config)}/api/status`;
|
|
1764
|
+
let lastStatus = null;
|
|
1708
1765
|
for (let attempt = 0; attempt < attempts; attempt += 1) {
|
|
1709
1766
|
try {
|
|
1710
|
-
|
|
1711
|
-
|
|
1767
|
+
lastStatus = await requestJson2(statusEndpoint, {
|
|
1768
|
+
timeout: 800,
|
|
1769
|
+
headers: {
|
|
1770
|
+
"X-Herdr-Host-Id": state.hostId,
|
|
1771
|
+
"X-Herdr-Host-Token": state.hostToken
|
|
1772
|
+
}
|
|
1773
|
+
});
|
|
1774
|
+
if (lastStatus.hosts?.some((host) => host.id === state.hostId)) return lastStatus;
|
|
1712
1775
|
} catch (error2) {
|
|
1713
|
-
|
|
1776
|
+
lastStatus = { ok: false, message: error2.message };
|
|
1714
1777
|
}
|
|
1715
1778
|
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
1716
1779
|
}
|
|
1717
|
-
const error = new Error(
|
|
1718
|
-
error.health =
|
|
1780
|
+
const error = new Error(lastStatus?.message || "the Herdr host connector did not register with the relay");
|
|
1781
|
+
error.health = lastStatus;
|
|
1719
1782
|
throw error;
|
|
1720
1783
|
}
|
|
1721
1784
|
async function statusServices() {
|
|
@@ -2301,11 +2364,13 @@ var require_updater = __commonJS({
|
|
|
2301
2364
|
"src/updater.js"(exports, module) {
|
|
2302
2365
|
"use strict";
|
|
2303
2366
|
var fs = __require("node:fs");
|
|
2367
|
+
var os = __require("node:os");
|
|
2304
2368
|
var path = __require("node:path");
|
|
2305
2369
|
var { spawn } = __require("node:child_process");
|
|
2306
2370
|
var { PACKAGE_ROOT } = require_config();
|
|
2307
2371
|
var PACKAGE_NAME = "herdr-remote";
|
|
2308
|
-
var
|
|
2372
|
+
var DEFAULT_REGISTRY = "https://registry.npmjs.org";
|
|
2373
|
+
var MIRROR_REGISTRY = "https://registry.npmmirror.com";
|
|
2309
2374
|
function currentVersion() {
|
|
2310
2375
|
try {
|
|
2311
2376
|
return __require(path.join(PACKAGE_ROOT, "package.json")).version;
|
|
@@ -2325,6 +2390,43 @@ var require_updater = __commonJS({
|
|
|
2325
2390
|
function canSelfUpdate2() {
|
|
2326
2391
|
return installKind2() === "npm";
|
|
2327
2392
|
}
|
|
2393
|
+
function normalizeRegistry(value) {
|
|
2394
|
+
if (typeof value !== "string") return null;
|
|
2395
|
+
const trimmed = value.trim().replace(/\/+$/, "");
|
|
2396
|
+
if (!/^https?:\/\//i.test(trimmed)) return null;
|
|
2397
|
+
return trimmed;
|
|
2398
|
+
}
|
|
2399
|
+
function registryFromNpmrc(filePath) {
|
|
2400
|
+
let contents;
|
|
2401
|
+
try {
|
|
2402
|
+
contents = fs.readFileSync(filePath, "utf8");
|
|
2403
|
+
} catch {
|
|
2404
|
+
return null;
|
|
2405
|
+
}
|
|
2406
|
+
let found = null;
|
|
2407
|
+
for (const rawLine of contents.split(/\r?\n/)) {
|
|
2408
|
+
const line = rawLine.trim();
|
|
2409
|
+
if (!line || line.startsWith("#") || line.startsWith(";")) continue;
|
|
2410
|
+
const match = /^registry\s*=\s*(.+)$/i.exec(line);
|
|
2411
|
+
if (match) found = normalizeRegistry(match[1].replace(/^["']|["']$/g, ""));
|
|
2412
|
+
}
|
|
2413
|
+
return found;
|
|
2414
|
+
}
|
|
2415
|
+
function registryCandidates({ env = process.env, home = os.homedir(), cwd = process.cwd() } = {}) {
|
|
2416
|
+
const candidates = [];
|
|
2417
|
+
const add = (value) => {
|
|
2418
|
+
const normalized = normalizeRegistry(value);
|
|
2419
|
+
if (normalized && !candidates.includes(normalized)) candidates.push(normalized);
|
|
2420
|
+
};
|
|
2421
|
+
add(env.npm_config_registry);
|
|
2422
|
+
add(env.NPM_CONFIG_REGISTRY);
|
|
2423
|
+
add(env.HERDR_REMOTE_REGISTRY);
|
|
2424
|
+
add(registryFromNpmrc(path.join(cwd, ".npmrc")));
|
|
2425
|
+
add(registryFromNpmrc(path.join(home, ".npmrc")));
|
|
2426
|
+
add(DEFAULT_REGISTRY);
|
|
2427
|
+
add(MIRROR_REGISTRY);
|
|
2428
|
+
return candidates;
|
|
2429
|
+
}
|
|
2328
2430
|
function compareVersions(a, b) {
|
|
2329
2431
|
const parse = (value) => String(value).split("-")[0].split(".").map((part) => Number.parseInt(part, 10) || 0);
|
|
2330
2432
|
const left = parse(a);
|
|
@@ -2336,39 +2438,64 @@ var require_updater = __commonJS({
|
|
|
2336
2438
|
}
|
|
2337
2439
|
return 0;
|
|
2338
2440
|
}
|
|
2339
|
-
async function
|
|
2340
|
-
const current = currentVersion();
|
|
2441
|
+
async function askRegistry(registry, { timeoutMs, fetchImpl }) {
|
|
2341
2442
|
const controller = new AbortController();
|
|
2342
2443
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
2343
2444
|
try {
|
|
2344
|
-
const response = await fetchImpl(
|
|
2445
|
+
const response = await fetchImpl(`${registry}/${PACKAGE_NAME}/latest`, {
|
|
2345
2446
|
signal: controller.signal,
|
|
2346
2447
|
headers: { Accept: "application/vnd.npm.install-v1+json" }
|
|
2347
2448
|
});
|
|
2348
|
-
if (!response.ok) {
|
|
2349
|
-
return { ok: false, current, errorKey: "update.errorNetwork" };
|
|
2350
|
-
}
|
|
2449
|
+
if (!response.ok) return { ok: false, message: `HTTP ${response.status ?? "?"}` };
|
|
2351
2450
|
const body = await response.json();
|
|
2352
2451
|
const latest = typeof body?.version === "string" ? body.version : null;
|
|
2353
|
-
if (!latest) return { ok: false,
|
|
2354
|
-
return {
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
latest,
|
|
2358
|
-
updateAvailable: compareVersions(latest, current) > 0
|
|
2359
|
-
};
|
|
2360
|
-
} catch {
|
|
2361
|
-
return { ok: false, current, errorKey: "update.errorNetwork" };
|
|
2452
|
+
if (!latest) return { ok: false, message: "registry answered without a version" };
|
|
2453
|
+
return { ok: true, latest };
|
|
2454
|
+
} catch (error) {
|
|
2455
|
+
return { ok: false, message: error?.name === "AbortError" ? "timed out" : String(error?.message || error) };
|
|
2362
2456
|
} finally {
|
|
2363
2457
|
clearTimeout(timer);
|
|
2364
2458
|
}
|
|
2365
2459
|
}
|
|
2460
|
+
async function checkForUpdate2({
|
|
2461
|
+
timeoutMs = 6e3,
|
|
2462
|
+
fetchImpl = globalThis.fetch,
|
|
2463
|
+
registries = registryCandidates()
|
|
2464
|
+
} = {}) {
|
|
2465
|
+
const current = currentVersion();
|
|
2466
|
+
const failures = [];
|
|
2467
|
+
for (const registry of registries) {
|
|
2468
|
+
const attempt = await askRegistry(registry, { timeoutMs, fetchImpl });
|
|
2469
|
+
if (attempt.ok) {
|
|
2470
|
+
return {
|
|
2471
|
+
ok: true,
|
|
2472
|
+
current,
|
|
2473
|
+
latest: attempt.latest,
|
|
2474
|
+
registry,
|
|
2475
|
+
updateAvailable: compareVersions(attempt.latest, current) > 0
|
|
2476
|
+
};
|
|
2477
|
+
}
|
|
2478
|
+
failures.push(`${registry}: ${attempt.message}`);
|
|
2479
|
+
}
|
|
2480
|
+
return {
|
|
2481
|
+
ok: false,
|
|
2482
|
+
current,
|
|
2483
|
+
errorKey: "update.errorNetwork",
|
|
2484
|
+
message: failures.join("; "),
|
|
2485
|
+
triedRegistries: registries
|
|
2486
|
+
};
|
|
2487
|
+
}
|
|
2366
2488
|
function performUpdate2({
|
|
2367
2489
|
spawnImpl = spawn,
|
|
2368
2490
|
timeoutMs = 18e4,
|
|
2369
2491
|
// Seam for tests: the suite runs from a checkout, where the guard below is
|
|
2370
2492
|
// correctly the only reachable outcome.
|
|
2371
|
-
installKindImpl = installKind2
|
|
2493
|
+
installKindImpl = installKind2,
|
|
2494
|
+
// The registry that just answered the version check. Installing from
|
|
2495
|
+
// somewhere the machine has been shown to reach beats installing from a
|
|
2496
|
+
// default it may have no route to. Empty means "whatever npm is configured
|
|
2497
|
+
// with", which is the right answer when no check has run.
|
|
2498
|
+
registry = ""
|
|
2372
2499
|
} = {}) {
|
|
2373
2500
|
return new Promise((resolve) => {
|
|
2374
2501
|
const kind = installKindImpl();
|
|
@@ -2376,7 +2503,10 @@ var require_updater = __commonJS({
|
|
|
2376
2503
|
resolve({ ok: false, errorKey: `update.cannot.${kind}` });
|
|
2377
2504
|
return;
|
|
2378
2505
|
}
|
|
2379
|
-
const
|
|
2506
|
+
const args = ["install", "-g", `${PACKAGE_NAME}@latest`];
|
|
2507
|
+
const normalizedRegistry = normalizeRegistry(registry);
|
|
2508
|
+
if (normalizedRegistry) args.push("--registry", normalizedRegistry);
|
|
2509
|
+
const child = spawnImpl("npm", args, {
|
|
2380
2510
|
encoding: "utf8",
|
|
2381
2511
|
timeout: timeoutMs
|
|
2382
2512
|
});
|
|
@@ -2396,12 +2526,15 @@ var require_updater = __commonJS({
|
|
|
2396
2526
|
}
|
|
2397
2527
|
module.exports = {
|
|
2398
2528
|
PACKAGE_NAME,
|
|
2529
|
+
DEFAULT_REGISTRY,
|
|
2530
|
+
MIRROR_REGISTRY,
|
|
2399
2531
|
canSelfUpdate: canSelfUpdate2,
|
|
2400
2532
|
checkForUpdate: checkForUpdate2,
|
|
2401
2533
|
compareVersions,
|
|
2402
2534
|
currentVersion,
|
|
2403
2535
|
installKind: installKind2,
|
|
2404
|
-
performUpdate: performUpdate2
|
|
2536
|
+
performUpdate: performUpdate2,
|
|
2537
|
+
registryCandidates
|
|
2405
2538
|
};
|
|
2406
2539
|
}
|
|
2407
2540
|
});
|
|
@@ -2728,12 +2861,26 @@ function relayStartCommand(config, password) {
|
|
|
2728
2861
|
return parts.join(" ");
|
|
2729
2862
|
}
|
|
2730
2863
|
async function probeRelay(config) {
|
|
2864
|
+
const origin = (0, import_config.resolveAdminOrigin)(config);
|
|
2865
|
+
let health;
|
|
2731
2866
|
try {
|
|
2732
|
-
|
|
2733
|
-
return { ok: true, version: health.version, hosts: health.hosts };
|
|
2867
|
+
health = await (0, import_service.requestJson)(`${origin}/healthz`, { timeout: 4e3 });
|
|
2734
2868
|
} catch (error) {
|
|
2735
2869
|
return { ok: false, message: error.message };
|
|
2736
2870
|
}
|
|
2871
|
+
try {
|
|
2872
|
+
const runtime = (0, import_service.ensureRuntime)();
|
|
2873
|
+
const status = await (0, import_service.requestJson)(`${origin}/api/status`, {
|
|
2874
|
+
timeout: 4e3,
|
|
2875
|
+
headers: {
|
|
2876
|
+
"X-Herdr-Host-Id": runtime.hostId,
|
|
2877
|
+
"X-Herdr-Host-Token": runtime.hostToken
|
|
2878
|
+
}
|
|
2879
|
+
});
|
|
2880
|
+
return { ok: true, version: String(health.version || status.version || ""), hosts: Array.isArray(status.hosts) ? status.hosts.length : 0 };
|
|
2881
|
+
} catch {
|
|
2882
|
+
return { ok: true, version: String(health.version || ""), hosts: void 0 };
|
|
2883
|
+
}
|
|
2737
2884
|
}
|
|
2738
2885
|
function formatUptime(seconds, t) {
|
|
2739
2886
|
if (!Number.isFinite(seconds)) return t("common.unknown");
|
|
@@ -3105,6 +3252,7 @@ function RelayScreen({ ctx }) {
|
|
|
3105
3252
|
const [revealTokens, setRevealTokens] = useState5(false);
|
|
3106
3253
|
const [showEnv, setShowEnv] = useState5(false);
|
|
3107
3254
|
const [password, setPassword] = useState5(ctx.runtime.relayPassword || "");
|
|
3255
|
+
const official = (0, import_settings_model.isOfficialRelay)(draft);
|
|
3108
3256
|
const fields = useMemo2(
|
|
3109
3257
|
() => (0, import_settings_model.fieldsForMode)(draft.relay.mode).filter((field) => ["mode", "port", "lanHost", "remoteUrl", "publicUrl"].includes(field.id)),
|
|
3110
3258
|
[draft.relay.mode]
|
|
@@ -3112,20 +3260,24 @@ function RelayScreen({ ctx }) {
|
|
|
3112
3260
|
const entries = [
|
|
3113
3261
|
...fields.map((field) => ({
|
|
3114
3262
|
id: field.id,
|
|
3115
|
-
|
|
3263
|
+
// The official relay's address is ours and its browser URL follows from
|
|
3264
|
+
// it, so neither is offered for editing: an editable box holding a value
|
|
3265
|
+
// that must not change is an invitation to break the setup.
|
|
3266
|
+
kind: official && (field.id === "remoteUrl" || field.id === "publicUrl") ? "readonly" : "field",
|
|
3116
3267
|
fieldKind: field.kind,
|
|
3117
3268
|
label: t(field.labelKey)
|
|
3118
3269
|
})),
|
|
3119
3270
|
// The password only matters when talking to a relay somebody else started;
|
|
3120
|
-
// a local relay is configured with our own token automatically
|
|
3121
|
-
|
|
3271
|
+
// a local relay is configured with our own token automatically, and the
|
|
3272
|
+
// official one authenticates workstations by their own host token.
|
|
3273
|
+
...draft.relay.mode === "remote" && !official ? [{ id: "password", kind: "password", label: t("relay.password") }] : [],
|
|
3122
3274
|
// Saving needs a row of its own. Every field here only edits a draft, and
|
|
3123
3275
|
// the services restart from what is on disk — with `s` as the sole way to
|
|
3124
3276
|
// commit, a change could look applied, survive a restart, and never take
|
|
3125
3277
|
// effect. It is also the only way to save with the mouse.
|
|
3126
3278
|
{ id: "save", kind: "action", label: t("common.save") },
|
|
3127
3279
|
{ id: "test", kind: "action", label: t("relay.test") },
|
|
3128
|
-
...draft.relay.mode === "remote" ? [
|
|
3280
|
+
...draft.relay.mode === "remote" && !official ? [
|
|
3129
3281
|
{ id: "reveal", kind: "action", label: revealTokens ? t("relay.hidePassword") : t("relay.showPassword") },
|
|
3130
3282
|
{ id: "env", kind: "action", label: t("relay.envSnippet") }
|
|
3131
3283
|
] : [],
|
|
@@ -3160,6 +3312,10 @@ function RelayScreen({ ctx }) {
|
|
|
3160
3312
|
const activate = (id) => {
|
|
3161
3313
|
const entry = entries.find((candidate) => candidate.id === id);
|
|
3162
3314
|
if (!entry) return;
|
|
3315
|
+
if (entry.kind === "readonly") {
|
|
3316
|
+
ctx.notify(t("relay.officialFixed"), "info");
|
|
3317
|
+
return;
|
|
3318
|
+
}
|
|
3163
3319
|
if (entry.kind === "field" || entry.kind === "password") {
|
|
3164
3320
|
ctx.setEditing(id);
|
|
3165
3321
|
return;
|
|
@@ -3214,14 +3370,13 @@ function RelayScreen({ ctx }) {
|
|
|
3214
3370
|
{ id: "official", label: t("mode.official"), description: t("mode.official.description") },
|
|
3215
3371
|
{ id: "remote", label: t("mode.remote"), description: t("mode.remote.description") }
|
|
3216
3372
|
],
|
|
3217
|
-
current:
|
|
3373
|
+
current: (0, import_settings_model.selectedMode)(draft),
|
|
3218
3374
|
onPick: (choice) => {
|
|
3375
|
+
if (!applyField("mode", choice)) return;
|
|
3219
3376
|
if (choice === "official") {
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
return;
|
|
3377
|
+
setPassword("");
|
|
3378
|
+
(0, import_service.setRelayPassword)("");
|
|
3223
3379
|
}
|
|
3224
|
-
applyField("mode", choice);
|
|
3225
3380
|
ctx.setEditing(null);
|
|
3226
3381
|
},
|
|
3227
3382
|
onCancel: () => ctx.setEditing(null)
|
|
@@ -3285,10 +3440,14 @@ function RelayScreen({ ctx }) {
|
|
|
3285
3440
|
},
|
|
3286
3441
|
onCancel: () => ctx.setEditing(null)
|
|
3287
3442
|
}
|
|
3443
|
+
) : entry.kind === "readonly" ? (
|
|
3444
|
+
// Fixed by us, so it is printed rather than offered for editing.
|
|
3445
|
+
/* @__PURE__ */ jsx7(Text6, { color: theme.muted, children: `${(0, import_settings_model.getField)(draft, entry.id) || placeholderText(ctx, entry.id)} (${t("relay.locked")})` })
|
|
3288
3446
|
) : entry.fieldKind === "choice" ? (
|
|
3289
3447
|
// Choice fields are picked from a list, never typed, so they
|
|
3290
|
-
// show the translated label rather than the stored id
|
|
3291
|
-
|
|
3448
|
+
// show the translated label rather than the stored id — and the
|
|
3449
|
+
// official relay is named as itself, not as "self-hosted".
|
|
3450
|
+
/* @__PURE__ */ jsx7(Text6, { children: t(`mode.${(0, import_settings_model.selectedMode)(draft)}`) })
|
|
3292
3451
|
) : /* @__PURE__ */ jsx7(
|
|
3293
3452
|
TextField,
|
|
3294
3453
|
{
|
|
@@ -3305,13 +3464,13 @@ function RelayScreen({ ctx }) {
|
|
|
3305
3464
|
entry.id
|
|
3306
3465
|
)),
|
|
3307
3466
|
ctx.dirty ? /* @__PURE__ */ jsx7(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx7(Text6, { color: theme.warn, children: t("hint.unsavedChanges") }) }) : null,
|
|
3308
|
-
draft.relay.mode === "remote" ? /* @__PURE__ */ jsx7(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx7(Text6, { color: theme.muted, children: t("relay.passwordHint") }) }) : null,
|
|
3467
|
+
draft.relay.mode === "remote" ? /* @__PURE__ */ jsx7(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx7(Text6, { color: theme.muted, children: official ? t("relay.officialHint") : t("relay.passwordHint") }) }) : null,
|
|
3309
3468
|
/* @__PURE__ */ jsx7(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx7(Row, { label: t("relay.identity"), children: /* @__PURE__ */ jsx7(Text6, { color: theme.muted, children: ctx.runtime.hostId }) }) }),
|
|
3310
3469
|
showEnv ? /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", marginTop: 1, borderStyle: "round", borderColor: theme.border, paddingX: 1, children: [
|
|
3311
3470
|
/* @__PURE__ */ jsx7(Text6, { color: theme.muted, children: t("relay.envHint") }),
|
|
3312
3471
|
/* @__PURE__ */ jsx7(Text6, { children: relayStartCommand(ctx.config, password) })
|
|
3313
3472
|
] }) : null,
|
|
3314
|
-
/* @__PURE__ */ jsx7(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx7(Text6, { color: theme.muted, children: t("relay.docsHint") }) }),
|
|
3473
|
+
official ? null : /* @__PURE__ */ jsx7(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx7(Text6, { color: theme.muted, children: t("relay.docsHint") }) }),
|
|
3315
3474
|
/* @__PURE__ */ jsx7(Message, { text: ctx.message?.text ?? null, level: ctx.message?.level ?? "info" })
|
|
3316
3475
|
] });
|
|
3317
3476
|
}
|
|
@@ -3603,6 +3762,7 @@ function About({ ctx }) {
|
|
|
3603
3762
|
const { t, draft } = ctx;
|
|
3604
3763
|
const [selected, setSelected] = useState8("auto");
|
|
3605
3764
|
const [update, setUpdate] = useState8({ phase: "idle" });
|
|
3765
|
+
const registryRef = useState8(() => ({ current: "" }))[0];
|
|
3606
3766
|
const detected = detectLocale({ preference: "auto" });
|
|
3607
3767
|
const languageOptions = [
|
|
3608
3768
|
{ id: "auto", label: t("about.languageAuto", { detected }) },
|
|
@@ -3634,13 +3794,15 @@ function About({ ctx }) {
|
|
|
3634
3794
|
const result = await (0, import_updater.checkForUpdate)();
|
|
3635
3795
|
if (!result.ok) {
|
|
3636
3796
|
setUpdate({ phase: "error", messageKey: result.errorKey ?? "update.errorNetwork" });
|
|
3797
|
+
if (result.message) ctx.notify(t("update.errorNetworkDetail", { message: result.message }), "error");
|
|
3637
3798
|
return;
|
|
3638
3799
|
}
|
|
3800
|
+
registryRef.current = result.registry ?? "";
|
|
3639
3801
|
setUpdate(result.updateAvailable ? { phase: "available", latest: result.latest } : { phase: "current", latest: result.latest });
|
|
3640
3802
|
};
|
|
3641
3803
|
const runUpdate = async (latest) => {
|
|
3642
3804
|
setUpdate({ phase: "updating", latest });
|
|
3643
|
-
const result = await (0, import_updater.performUpdate)();
|
|
3805
|
+
const result = await (0, import_updater.performUpdate)({ registry: registryRef.current });
|
|
3644
3806
|
if (!result.ok) {
|
|
3645
3807
|
setUpdate({ phase: "error", messageKey: result.errorKey ?? "update.errorFailed" });
|
|
3646
3808
|
ctx.notify(t("update.errorFailed"), "error");
|
|
@@ -3717,7 +3879,7 @@ function About({ ctx }) {
|
|
|
3717
3879
|
children: updateLabel
|
|
3718
3880
|
}
|
|
3719
3881
|
) }),
|
|
3720
|
-
/* @__PURE__ */ jsx10(Row, { label: t("about.version"), children: /* @__PURE__ */ jsx10(Text9, { color: theme.muted, children: "0.2.
|
|
3882
|
+
/* @__PURE__ */ jsx10(Row, { label: t("about.version"), children: /* @__PURE__ */ jsx10(Text9, { color: theme.muted, children: "0.2.5" }) }),
|
|
3721
3883
|
/* @__PURE__ */ jsx10(Row, { label: t("about.configPath"), children: /* @__PURE__ */ jsx10(Text9, { color: theme.muted, children: (0, import_config.configPath)() }) }),
|
|
3722
3884
|
/* @__PURE__ */ jsx10(Row, { label: t("about.statePath"), children: /* @__PURE__ */ jsx10(Text9, { color: theme.muted, children: (0, import_config.stateDir)() }) }),
|
|
3723
3885
|
/* @__PURE__ */ jsx10(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx10(Text9, { color: theme.muted, children: t("about.docs") }) }),
|
|
@@ -3848,16 +4010,16 @@ function Wizard({ ctx, onDone }) {
|
|
|
3848
4010
|
description: t("mode.remote.description")
|
|
3849
4011
|
}
|
|
3850
4012
|
],
|
|
3851
|
-
current:
|
|
4013
|
+
current: (0, import_settings_model.selectedMode)(draft),
|
|
3852
4014
|
onPick: (choice) => {
|
|
3853
4015
|
if (choice === "official") {
|
|
3854
|
-
if (!
|
|
4016
|
+
if (!apply("mode", "official")) return;
|
|
3855
4017
|
(0, import_service.setRelayPassword)("");
|
|
3856
4018
|
advance("access", stepsFor("remote", import_config.OFFICIAL_RELAY_URL));
|
|
3857
4019
|
return;
|
|
3858
4020
|
}
|
|
3859
4021
|
if (apply("mode", choice)) {
|
|
3860
|
-
advance("access", stepsFor(choice, draft.relay.remoteUrl));
|
|
4022
|
+
advance("access", stepsFor(choice, choice === "remote" ? "" : draft.relay.remoteUrl));
|
|
3861
4023
|
}
|
|
3862
4024
|
},
|
|
3863
4025
|
onCancel: back
|