@linxin666/dsh-remote-web-ui 0.3.6 → 0.3.9
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.i18n.yaml +2 -2
- package/README.md +77 -468
- package/README.zh.md +83 -113
- package/lib/client.js +955 -203
- package/lib/client.js.map +1 -1
- package/lib/index.js +1136 -1466
- package/lib/types/client/FooterRemoteEntry.d.ts +6 -7
- package/lib/types/client/FooterRemoteEntry.d.ts.map +1 -1
- package/lib/types/client/FooterRemoteEntry.js +1 -1
- package/lib/types/client/RemoteEntry.d.ts +7 -4
- package/lib/types/client/RemoteEntry.d.ts.map +1 -1
- package/lib/types/client/RemoteEntry.js +7 -10
- package/lib/types/client/RemotePanel.d.ts +2 -2
- package/lib/types/client/RemotePanel.d.ts.map +1 -1
- package/lib/types/client/RemotePanel.js +2 -2
- package/lib/types/client/RemoteSettingsCard.d.ts +9 -5
- package/lib/types/client/RemoteSettingsCard.d.ts.map +1 -1
- package/lib/types/client/RemoteSettingsCard.js +56 -3
- package/lib/types/client/deep-link.d.ts +10 -13
- package/lib/types/client/deep-link.d.ts.map +1 -1
- package/lib/types/client/deep-link.js +14 -74
- package/lib/types/client/index.d.ts +2 -6
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/index.js +73 -39
- package/lib/types/client/locales.d.ts +26 -12
- package/lib/types/client/locales.d.ts.map +1 -1
- package/lib/types/client/locales.js +36 -22
- package/lib/types/client/mobile-adapt.d.ts +40 -0
- package/lib/types/client/mobile-adapt.d.ts.map +1 -0
- package/lib/types/client/mobile-adapt.js +967 -0
- package/lib/types/client/pair-api.d.ts +24 -6
- package/lib/types/client/pair-api.d.ts.map +1 -1
- package/lib/types/client/pair-api.js +9 -14
- package/lib/types/client/remote-channel.d.ts +3 -0
- package/lib/types/client/remote-channel.d.ts.map +1 -1
- package/lib/types/client/remote-channel.js +35 -3
- package/lib/types/client/settings-form.d.ts +35 -43
- package/lib/types/client/settings-form.d.ts.map +1 -1
- package/lib/types/client/settings-form.js +60 -53
- package/lib/types/firewall.d.ts +75 -0
- package/lib/types/firewall.d.ts.map +1 -0
- package/lib/types/firewall.js +184 -0
- package/lib/types/gate.d.ts +11 -5
- package/lib/types/gate.d.ts.map +1 -1
- package/lib/types/gate.js +11 -5
- package/lib/types/index.d.ts +39 -10
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/index.js +206 -58
- package/lib/types/inner-auth.d.ts +32 -0
- package/lib/types/inner-auth.d.ts.map +1 -0
- package/lib/types/inner-auth.js +72 -0
- package/lib/types/lan-bind-plan.d.ts +55 -0
- package/lib/types/lan-bind-plan.d.ts.map +1 -0
- package/lib/types/lan-bind-plan.js +60 -0
- package/lib/types/lan-bind.d.ts +69 -0
- package/lib/types/lan-bind.d.ts.map +1 -0
- package/lib/types/lan-bind.js +128 -0
- package/lib/types/loopback-proxy.d.ts +9 -2
- package/lib/types/loopback-proxy.d.ts.map +1 -1
- package/lib/types/loopback-proxy.js +24 -2
- package/lib/types/pairing.d.ts +15 -3
- package/lib/types/pairing.d.ts.map +1 -1
- package/lib/types/pairing.js +20 -6
- package/lib/types/remote-api.d.ts +30 -13
- package/lib/types/remote-api.d.ts.map +1 -1
- package/lib/types/remote-api.js +55 -42
- package/lib/types/remote-channel-boot.d.ts +21 -2
- package/lib/types/remote-channel-boot.d.ts.map +1 -1
- package/lib/types/remote-channel-boot.js +65 -3
- package/lib/types/remote-channel-rules.d.ts +8 -0
- package/lib/types/remote-channel-rules.d.ts.map +1 -1
- package/lib/types/remote-channel-rules.js +9 -2
- package/lib/types/remote-methods.d.ts +45 -11
- package/lib/types/remote-methods.d.ts.map +1 -1
- package/lib/types/remote-methods.js +56 -27
- package/lib/types/remote-presence-pet.d.ts +51 -0
- package/lib/types/remote-presence-pet.d.ts.map +1 -0
- package/lib/types/remote-presence-pet.js +101 -0
- package/lib/types/routes.d.ts +76 -4
- package/lib/types/routes.d.ts.map +1 -1
- package/lib/types/routes.js +336 -19
- package/lib/types/tunnel.d.ts.map +1 -1
- package/lib/types/tunnel.js +7 -1
- package/package.json +20 -18
- package/src/client/FooterRemoteEntry.tsx +9 -10
- package/src/client/RemoteEntry.tsx +13 -14
- package/src/client/RemotePanel.tsx +5 -16
- package/src/client/RemoteSettingsCard.tsx +72 -13
- package/src/client/deep-link.ts +14 -75
- package/src/client/index.ts +77 -39
- package/src/client/locales.ts +36 -22
- package/src/client/mobile-adapt.ts +913 -0
- package/src/client/pair-api.ts +26 -15
- package/src/client/remote-channel.ts +31 -3
- package/src/client/settings-form.ts +78 -92
- package/src/dsh-home.ts +1 -1
- package/src/firewall.ts +230 -0
- package/src/gate.ts +11 -5
- package/src/index.ts +235 -65
- package/src/inner-auth.ts +85 -0
- package/src/lan-bind-plan.ts +81 -0
- package/src/lan-bind.ts +145 -0
- package/src/loopback-proxy.ts +34 -0
- package/src/pairing.persist.test.ts +1 -1
- package/src/pairing.ts +20 -6
- package/src/remote-api.ts +67 -45
- package/src/remote-channel-boot.ts +70 -3
- package/src/remote-channel-rules.ts +17 -2
- package/src/remote-methods.ts +58 -27
- package/src/remote-presence-pet.ts +129 -0
- package/src/routes.ts +358 -19
- package/src/tunnel.ts +7 -1
- package/assets/apple-touch-icon.png +0 -0
- package/assets/mobile-icon-192.png +0 -0
- package/assets/mobile-icon-512.png +0 -0
- package/assets/mobile-service-worker.js +0 -63
- package/lib/mobile.js +0 -17658
- package/lib/mobile.js.map +0 -1
- package/lib/types/mobile/PairRequiredView.d.ts +0 -7
- package/lib/types/mobile/PairRequiredView.d.ts.map +0 -1
- package/lib/types/mobile/PairRequiredView.js +0 -28
- package/lib/types/mobile/PairRequiredView.test.d.ts +0 -2
- package/lib/types/mobile/PairRequiredView.test.d.ts.map +0 -1
- package/lib/types/mobile/PairRequiredView.test.js +0 -24
- package/lib/types/mobile/api.d.ts +0 -145
- package/lib/types/mobile/api.d.ts.map +0 -1
- package/lib/types/mobile/api.js +0 -103
- package/lib/types/mobile/index.d.ts +0 -10
- package/lib/types/mobile/index.d.ts.map +0 -1
- package/lib/types/mobile/index.js +0 -38
- package/lib/types/mobile/markdown.d.ts +0 -34
- package/lib/types/mobile/markdown.d.ts.map +0 -1
- package/lib/types/mobile/markdown.js +0 -285
- package/lib/types/mobile/markdown.test.d.ts +0 -2
- package/lib/types/mobile/markdown.test.d.ts.map +0 -1
- package/lib/types/mobile/markdown.test.js +0 -79
- package/lib/types/mobile/messages.d.ts +0 -149
- package/lib/types/mobile/messages.d.ts.map +0 -1
- package/lib/types/mobile/messages.js +0 -561
- package/lib/types/mobile/messages.test.d.ts +0 -2
- package/lib/types/mobile/messages.test.d.ts.map +0 -1
- package/lib/types/mobile/messages.test.js +0 -356
- package/lib/types/mobile/mobile-styles.d.ts +0 -6
- package/lib/types/mobile/mobile-styles.d.ts.map +0 -1
- package/lib/types/mobile/mobile-styles.js +0 -1438
- package/lib/types/mobile/mobile-theme.d.ts +0 -22
- package/lib/types/mobile/mobile-theme.d.ts.map +0 -1
- package/lib/types/mobile/mobile-theme.js +0 -70
- package/lib/types/mobile/mobile-theme.test.d.ts +0 -2
- package/lib/types/mobile/mobile-theme.test.d.ts.map +0 -1
- package/lib/types/mobile/mobile-theme.test.js +0 -71
- package/lib/types/mobile/mux.d.ts +0 -128
- package/lib/types/mobile/mux.d.ts.map +0 -1
- package/lib/types/mobile/mux.js +0 -305
- package/lib/types/mobile/mux.test.d.ts +0 -2
- package/lib/types/mobile/mux.test.d.ts.map +0 -1
- package/lib/types/mobile/mux.test.js +0 -267
- package/lib/types/mobile/pairing.d.ts +0 -31
- package/lib/types/mobile/pairing.d.ts.map +0 -1
- package/lib/types/mobile/pairing.js +0 -62
- package/lib/types/mobile/rpc.d.ts +0 -38
- package/lib/types/mobile/rpc.d.ts.map +0 -1
- package/lib/types/mobile/rpc.js +0 -83
- package/lib/types/mobile/theme-toggle.d.ts +0 -12
- package/lib/types/mobile/theme-toggle.d.ts.map +0 -1
- package/lib/types/mobile/theme-toggle.js +0 -26
- package/lib/types/mobile/views/App.d.ts +0 -57
- package/lib/types/mobile/views/App.d.ts.map +0 -1
- package/lib/types/mobile/views/App.js +0 -150
- package/lib/types/mobile/views/App.test.d.ts +0 -2
- package/lib/types/mobile/views/App.test.d.ts.map +0 -1
- package/lib/types/mobile/views/App.test.js +0 -52
- package/lib/types/mobile/views/ChatView.d.ts +0 -63
- package/lib/types/mobile/views/ChatView.d.ts.map +0 -1
- package/lib/types/mobile/views/ChatView.js +0 -821
- package/lib/types/mobile/views/ChatView.stream.test.d.ts +0 -2
- package/lib/types/mobile/views/ChatView.stream.test.d.ts.map +0 -1
- package/lib/types/mobile/views/ChatView.stream.test.js +0 -236
- package/lib/types/mobile/views/ChatView.test.d.ts +0 -2
- package/lib/types/mobile/views/ChatView.test.d.ts.map +0 -1
- package/lib/types/mobile/views/ChatView.test.js +0 -718
- package/lib/types/mobile/views/SessionListView.d.ts +0 -27
- package/lib/types/mobile/views/SessionListView.d.ts.map +0 -1
- package/lib/types/mobile/views/SessionListView.js +0 -139
- package/lib/types/mobile/views/SessionListView.test.d.ts +0 -2
- package/lib/types/mobile/views/SessionListView.test.d.ts.map +0 -1
- package/lib/types/mobile/views/SessionListView.test.js +0 -167
- package/lib/types/mobile/views/WorkspaceView.d.ts +0 -21
- package/lib/types/mobile/views/WorkspaceView.d.ts.map +0 -1
- package/lib/types/mobile/views/WorkspaceView.js +0 -93
- package/lib/types/mobile/views/WorkspaceView.test.d.ts +0 -2
- package/lib/types/mobile/views/WorkspaceView.test.d.ts.map +0 -1
- package/lib/types/mobile/views/WorkspaceView.test.js +0 -183
- package/lib/types/mobile-api.d.ts +0 -65
- package/lib/types/mobile-api.d.ts.map +0 -1
- package/lib/types/mobile-api.js +0 -404
- package/lib/types/mobile-pending.d.ts +0 -38
- package/lib/types/mobile-pending.d.ts.map +0 -1
- package/lib/types/mobile-pending.js +0 -59
- package/lib/types/mobile-pwa.d.ts +0 -6
- package/lib/types/mobile-pwa.d.ts.map +0 -1
- package/lib/types/mobile-pwa.js +0 -17
- package/lib/types/mobile-routes.d.ts +0 -13
- package/lib/types/mobile-routes.d.ts.map +0 -1
- package/lib/types/mobile-routes.js +0 -217
- package/lib/types/paired-model-catalog.d.ts +0 -17
- package/lib/types/paired-model-catalog.d.ts.map +0 -1
- package/lib/types/paired-model-catalog.js +0 -311
- package/src/mobile/PairRequiredView.test.tsx +0 -28
- package/src/mobile/PairRequiredView.tsx +0 -58
- package/src/mobile/api.ts +0 -229
- package/src/mobile/index.tsx +0 -41
- package/src/mobile/markdown.test.ts +0 -91
- package/src/mobile/markdown.ts +0 -291
- package/src/mobile/messages.test.ts +0 -402
- package/src/mobile/messages.ts +0 -685
- package/src/mobile/mobile-styles.ts +0 -1439
- package/src/mobile/mobile-theme.test.ts +0 -84
- package/src/mobile/mobile-theme.ts +0 -76
- package/src/mobile/mux.test.ts +0 -314
- package/src/mobile/mux.ts +0 -336
- package/src/mobile/pairing.ts +0 -77
- package/src/mobile/rpc.ts +0 -90
- package/src/mobile/theme-toggle.tsx +0 -47
- package/src/mobile/views/App.test.tsx +0 -62
- package/src/mobile/views/App.tsx +0 -213
- package/src/mobile/views/ChatView.stream.test.tsx +0 -268
- package/src/mobile/views/ChatView.test.tsx +0 -816
- package/src/mobile/views/ChatView.tsx +0 -1342
- package/src/mobile/views/SessionListView.test.tsx +0 -207
- package/src/mobile/views/SessionListView.tsx +0 -244
- package/src/mobile/views/WorkspaceView.test.tsx +0 -227
- package/src/mobile/views/WorkspaceView.tsx +0 -245
- package/src/mobile-api.ts +0 -418
- package/src/mobile-pending.ts +0 -88
- package/src/mobile-pwa.ts +0 -19
- package/src/mobile-routes.ts +0 -231
- package/src/paired-model-catalog.ts +0 -272
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Remote-presence to pet-visibility link (user requirement): while at least
|
|
3
|
+
* one paired device is online (an active phone mirror session), the
|
|
4
|
+
* host-global pet is hidden through the pet's OWN hide switch (the
|
|
5
|
+
* PetService.setVisible RPC, the same one the pet's hide button uses);
|
|
6
|
+
* once the last device stays offline past a grace window, the pet is
|
|
7
|
+
* restored. The pet plugin is optional: without it (or on any pet failure)
|
|
8
|
+
* the link is a no-op - the remote-control feature never depends on the
|
|
9
|
+
* pet being installed.
|
|
10
|
+
*
|
|
11
|
+
* The visibility is host-global by design (the pet is host-global, no
|
|
12
|
+
* session dimension): the desktop and the phone share one pet, so the link
|
|
13
|
+
* hides it while the operator is away on a phone mirror and restores it
|
|
14
|
+
* when the mirror ends. A manual user hide is respected: if the pet is
|
|
15
|
+
* already hidden when the first device comes online, nothing is recorded
|
|
16
|
+
* and nothing is restored later.
|
|
17
|
+
*/
|
|
18
|
+
/** Default restore grace: the presence sweep flips a device offline after
|
|
19
|
+
* ~25 s, and a phone that was briefly backgrounded should not flicker the
|
|
20
|
+
* pet; 2 minutes keeps the restore stable. */
|
|
21
|
+
const DEFAULT_RESTORE_AFTER_MS = 120_000;
|
|
22
|
+
const nodeTimers = { setTimeout, clearTimeout };
|
|
23
|
+
/**
|
|
24
|
+
* Start the presence link. Returns the disposer (withdraws the state
|
|
25
|
+
* subscription and cancels a pending restore).
|
|
26
|
+
* @param deps - pairing stream + pet seam (+ test seams).
|
|
27
|
+
*/
|
|
28
|
+
export function startRemotePresencePet(deps) {
|
|
29
|
+
const restoreAfterMs = deps.restoreAfterMs ?? DEFAULT_RESTORE_AFTER_MS;
|
|
30
|
+
const timers = deps.timers ?? nodeTimers;
|
|
31
|
+
let previousOnline = false;
|
|
32
|
+
let hiddenByRemote = false;
|
|
33
|
+
let restoreTimer;
|
|
34
|
+
let disposed = false;
|
|
35
|
+
const clearRestore = () => {
|
|
36
|
+
if (restoreTimer !== undefined) {
|
|
37
|
+
timers.clearTimeout(restoreTimer);
|
|
38
|
+
restoreTimer = undefined;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
const scheduleRestore = () => {
|
|
42
|
+
clearRestore();
|
|
43
|
+
restoreTimer = timers.setTimeout(() => {
|
|
44
|
+
restoreTimer = undefined;
|
|
45
|
+
restoreAfterTick();
|
|
46
|
+
}, restoreAfterMs);
|
|
47
|
+
};
|
|
48
|
+
const restoreAfterTick = () => {
|
|
49
|
+
if (disposed || !hiddenByRemote)
|
|
50
|
+
return;
|
|
51
|
+
const pet = deps.pet();
|
|
52
|
+
if (pet === undefined)
|
|
53
|
+
return;
|
|
54
|
+
hiddenByRemote = false;
|
|
55
|
+
void pet.setVisible(true).catch(() => {
|
|
56
|
+
// The pet bridge failed (e.g. the pet host was mid-reload): the pet
|
|
57
|
+
// stays whatever it is; the next connect/disconnect cycle re-evaluates.
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
const hideForRemote = () => {
|
|
61
|
+
if (hiddenByRemote)
|
|
62
|
+
return;
|
|
63
|
+
const pet = deps.pet();
|
|
64
|
+
if (pet === undefined)
|
|
65
|
+
return;
|
|
66
|
+
void pet.state().then((value) => {
|
|
67
|
+
if (disposed || hiddenByRemote)
|
|
68
|
+
return;
|
|
69
|
+
const visible = value.display?.visible;
|
|
70
|
+
if (visible !== true)
|
|
71
|
+
return;
|
|
72
|
+
hiddenByRemote = true;
|
|
73
|
+
return pet.setVisible(false).catch(() => {
|
|
74
|
+
// Hide failed: leave the flag unset so a later transition retries.
|
|
75
|
+
hiddenByRemote = false;
|
|
76
|
+
});
|
|
77
|
+
}, () => {
|
|
78
|
+
// The state read failed; do not record a hide we never performed.
|
|
79
|
+
});
|
|
80
|
+
};
|
|
81
|
+
const handle = (snapshot) => {
|
|
82
|
+
const online = snapshot.phase === 'connected' && snapshot.onlineCount > 0;
|
|
83
|
+
if (online && !previousOnline) {
|
|
84
|
+
cancelRestoreAndClear();
|
|
85
|
+
hideForRemote();
|
|
86
|
+
}
|
|
87
|
+
else if (!online && previousOnline) {
|
|
88
|
+
scheduleRestore();
|
|
89
|
+
}
|
|
90
|
+
previousOnline = online;
|
|
91
|
+
};
|
|
92
|
+
const cancelRestoreAndClear = () => {
|
|
93
|
+
clearRestore();
|
|
94
|
+
};
|
|
95
|
+
const unsubscribe = deps.onState(handle);
|
|
96
|
+
return () => {
|
|
97
|
+
disposed = true;
|
|
98
|
+
unsubscribe();
|
|
99
|
+
clearRestore();
|
|
100
|
+
};
|
|
101
|
+
}
|
package/lib/types/routes.d.ts
CHANGED
|
@@ -3,9 +3,14 @@
|
|
|
3
3
|
* under /api: the webserver matches exact paths before the connection
|
|
4
4
|
* plugin's /api prefix, so these handlers own the full response lifecycle
|
|
5
5
|
* and apply their own trust fence (loopback-only for control endpoints;
|
|
6
|
-
* loopback-or-LAN for the phone-facing accept/heartbeat/status). The
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* loopback-or-LAN for the phone-facing accept/heartbeat/status). The cookie
|
|
7
|
+
* set on accept is the device identity the plugin's own surfaces enforce:
|
|
8
|
+
* the /remote channel gate and the api/gate listener. Alongside the JSON
|
|
9
|
+
* family sit the phone-facing top-level pages (exact routes /pair-accept,
|
|
10
|
+
* /pair-app, /pair-app.sw.js) with their own LAN-or-public fence. Note that
|
|
11
|
+
* on the 0.1.2-alpha.2 cohort nothing emits api/gate — direct /api is
|
|
12
|
+
* governed by the harness fence + browser auth — while the /remote channel
|
|
13
|
+
* always enforces the pairing cookie itself.
|
|
9
14
|
*/
|
|
10
15
|
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
11
16
|
import type { WebRoute } from '@deepseek-ai/dsh-host-webserver';
|
|
@@ -26,6 +31,16 @@ import { type PairingService, type PairingSnapshot } from './pairing.ts';
|
|
|
26
31
|
* browser markers are same-origin.
|
|
27
32
|
*/
|
|
28
33
|
export declare function isTrustedApiRequest(request: IncomingMessage, trustedHosts: readonly string[]): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* The rate-limit bucket key for one accept attempt (pure; unit-tested).
|
|
36
|
+
* The first client-visible XFF hop separates buckets behind the auto-tunnel
|
|
37
|
+
* (every internet client arrives from 127.0.0.1 there) — but only for
|
|
38
|
+
* loopback peers, since a direct LAN client can rotate the header freely.
|
|
39
|
+
* @param socketIp - the socket peer address.
|
|
40
|
+
* @param forwarded - the first XFF hop, already trimmed, if any.
|
|
41
|
+
* @param bucket - page (GET /pair-accept) vs api (POST /api/pair/accept).
|
|
42
|
+
*/
|
|
43
|
+
export declare function acceptLimitKey(socketIp: string, forwarded: string | undefined, bucket: 'page' | 'api'): string;
|
|
29
44
|
/**
|
|
30
45
|
* The host authority of a configured public base URL, e.g. `foo.trycloudflare.com`
|
|
31
46
|
* from `https://foo.trycloudflare.com`. Undefined when the URL does not parse —
|
|
@@ -35,6 +50,38 @@ export declare function isTrustedApiRequest(request: IncomingMessage, trustedHos
|
|
|
35
50
|
* @returns the `host[:port]` authority the fence should trust.
|
|
36
51
|
*/
|
|
37
52
|
export declare function publicHostOf(url: string | undefined): string | undefined;
|
|
53
|
+
/**
|
|
54
|
+
* The cookieless device credential: pass the device id from the /pair-app
|
|
55
|
+
* URL into sessionStorage (and localStorage for tab reloads) before any app
|
|
56
|
+
* script runs - same key the boot patch and the channel gate read. The
|
|
57
|
+
* replaceState to '/' hides the credential URL from the address bar and
|
|
58
|
+
* leaves the SPA at its canonical root path. The reopen service worker is
|
|
59
|
+
* registered in the same breath: later navigations to '/' (history,
|
|
60
|
+
* bookmark, tab restore) must not fall through to the harness index gate,
|
|
61
|
+
* which the cookieless flow can never satisfy.
|
|
62
|
+
*/
|
|
63
|
+
export declare const APP_DEVICE_STORAGE_KEY = "dsh-remote-device";
|
|
64
|
+
export declare function appShellCaptureScript(deviceId: string): string;
|
|
65
|
+
/** Patch the official index document with the device-capture script. */
|
|
66
|
+
export declare function patchAppShell(html: string, deviceId: string): string;
|
|
67
|
+
/**
|
|
68
|
+
* The reopen service worker served at PAIR_PATHS.appServiceWorker. A paired
|
|
69
|
+
* phone comes back to `/` from history, bookmarks, or tab restore; the
|
|
70
|
+
* harness fallback seat answers that navigation with its browser-auth 401,
|
|
71
|
+
* and the cookieless mobile flow never holds a browser-auth cookie. The
|
|
72
|
+
* worker owns navigations to `/` instead: network-first through /pair-app
|
|
73
|
+
* (which validates the device cookie and refreshes its presence), the
|
|
74
|
+
* cached shell for offline opens, and a pass-through of the original
|
|
75
|
+
* request when the plugin no longer answers. Plain-HTTP LAN origins are not
|
|
76
|
+
* secure contexts, so the worker never registers there — the LAN reopen
|
|
77
|
+
* path stays "scan a fresh QR", which is cheap in-network.
|
|
78
|
+
*
|
|
79
|
+
* Kept as a plain string (same pattern as the capture script): it must load
|
|
80
|
+
* with no build step, run on every JS engine that ships service workers,
|
|
81
|
+
* and be assertable as source in tests. Bump SHELL_CACHE when the storage
|
|
82
|
+
* layout changes so old caches are pruned on activate.
|
|
83
|
+
*/
|
|
84
|
+
export declare function appServiceWorkerScript(): string;
|
|
38
85
|
/** Route paths (exact matches under /api). */
|
|
39
86
|
export declare const PAIR_PATHS: {
|
|
40
87
|
readonly issue: "/api/pair/issue";
|
|
@@ -44,6 +91,16 @@ export declare const PAIR_PATHS: {
|
|
|
44
91
|
readonly heartbeat: "/api/pair/heartbeat";
|
|
45
92
|
readonly status: "/api/pair/status";
|
|
46
93
|
readonly events: "/api/pair/events";
|
|
94
|
+
readonly lanBind: "/api/pair/lan-bind";
|
|
95
|
+
/** Top-level accept-and-redirect entry the QR link points at. */
|
|
96
|
+
readonly acceptPage: "/pair-accept";
|
|
97
|
+
/** The cookieless app landing: serves the official shell for a paired device. */
|
|
98
|
+
readonly appPage: "/pair-app";
|
|
99
|
+
/**
|
|
100
|
+
* The reopen service worker (registered by the capture script). Root-level
|
|
101
|
+
* path so its default script-directory scope already covers `/`.
|
|
102
|
+
*/
|
|
103
|
+
readonly appServiceWorker: "/pair-app.sw.js";
|
|
47
104
|
};
|
|
48
105
|
/**
|
|
49
106
|
* /api/pair request payload contracts. Each POST endpoint validates its body
|
|
@@ -54,7 +111,6 @@ export declare const PAIR_PATHS: {
|
|
|
54
111
|
* are tolerated exactly as the previous manual reads ignored them.
|
|
55
112
|
*/
|
|
56
113
|
export declare const issuePayloadSchema: z.ZodObject<{
|
|
57
|
-
workspaceId: z.ZodOptional<z.ZodString>;
|
|
58
114
|
address: z.ZodOptional<z.ZodString>;
|
|
59
115
|
}, z.core.$strip>;
|
|
60
116
|
export declare const acceptPayloadSchema: z.ZodObject<{
|
|
@@ -86,6 +142,22 @@ export interface PairRoutesDeps {
|
|
|
86
142
|
lanAddresses: readonly string[];
|
|
87
143
|
/** Current desktop gate policy, re-read for every status response. */
|
|
88
144
|
requirePairingForLan?: boolean | (() => boolean);
|
|
145
|
+
/**
|
|
146
|
+
* LAN-bind facts for the settings card (managed patch block state, live
|
|
147
|
+
* bind host/port, firewall summary). Re-read per request so a hot-reloaded
|
|
148
|
+
* rebind and a fresh toggle round are both reflected without a restart.
|
|
149
|
+
* The route is loopback-only; undefined drops it (tests).
|
|
150
|
+
*/
|
|
151
|
+
lanBindStatus?: () => Record<string, unknown>;
|
|
152
|
+
/**
|
|
153
|
+
* The official index document to serve on the /pair-app landing. The
|
|
154
|
+
* plugin fetches it from the inner loopback with its own credential and
|
|
155
|
+
* patches it with the device-capture script, so a paired device loads
|
|
156
|
+
* the app shell WITHOUT passing the harness index gate - the mobile flow
|
|
157
|
+
* then needs no browser cookie at all (the channel gate accepts the
|
|
158
|
+
* cookieless header/query credential). Undefined drops the route (tests).
|
|
159
|
+
*/
|
|
160
|
+
indexDocument?: (deviceId: string) => Promise<string | undefined>;
|
|
89
161
|
}
|
|
90
162
|
/**
|
|
91
163
|
* Build the /api/pair route family.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/routes.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAChE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAA;AAC/D,OAAO,EAAE,CAAC,EAAgB,MAAM,KAAK,CAAA;AACrC,OAAO,EAA0B,KAAK,cAAc,EAAE,KAAK,eAAe,EAAE,MAAM,cAAc,CAAA;AAKhG;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CA6BtG;AAKD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,CAK9G;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAOxE;AAKD;;;;;;;;;GASG;AACH,eAAO,MAAM,sBAAsB,sBAAsB,CAAA;AAEzD,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAI9D;AAED,wEAAwE;AACxE,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAMpE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAoD/C;AA4BD,8CAA8C;AAC9C,eAAO,MAAM,UAAU;;;;;;;;;IASrB,iEAAiE;;IAEjE,iFAAiF;;IAEjF;;;OAGG;;CAEK,CAAA;AAEV;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB;;iBAE7B,CAAA;AACF,eAAO,MAAM,mBAAmB;;iBAE9B,CAAA;AACF,eAAO,MAAM,mBAAmB;;iBAE9B,CAAA;AACF,eAAO,MAAM,uBAAuB,gCAA6B,CAAA;AAoBjE,gDAAgD;AAChD,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA0B;IAElD;;OAEG;gBACS,OAAO,EAAE,cAAc;IAInC,4DAA4D;IAC5D,IAAI,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,GAAG,IAAI;IAiBrD,kEAAkE;IAClE,IAAI,CAAC,QAAQ,EAAE,eAAe,GAAG,IAAI;IAYrC,wCAAwC;IACxC,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF;AAED,6CAA6C;AAC7C,MAAM,WAAW,cAAc;IAC7B,2BAA2B;IAC3B,OAAO,EAAE,cAAc,CAAA;IACvB,0EAA0E;IAC1E,YAAY,EAAE,SAAS,MAAM,EAAE,CAAA;IAC/B,sEAAsE;IACtE,oBAAoB,CAAC,EAAE,OAAO,GAAG,CAAC,MAAM,OAAO,CAAC,CAAA;IAChD;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC7C;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAA;CAClE;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,cAAc,GAAG,QAAQ,EAAE,CAmY3D"}
|