dsh-mobile 0.3.15 → 0.4.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/CHANGELOG.md +30 -0
- package/README.en.md +62 -10
- package/README.md +72 -19
- package/lib/cli.js +96 -81
- package/lib/cli.js.map +1 -1
- package/lib/client.js +736 -89
- package/lib/client.js.map +1 -1
- package/lib/index.d.mts +86 -2
- package/lib/index.mjs +653 -118
- package/lib/index.mjs.map +1 -1
- package/lib/mobile-layout.js +89 -34
- package/lib/mobile-layout.js.map +1 -1
- package/package.json +1 -1
package/lib/index.d.mts
CHANGED
|
@@ -85,6 +85,13 @@ interface SessionAuthorization {
|
|
|
85
85
|
readonly deviceId: string;
|
|
86
86
|
readonly expiresAt: number;
|
|
87
87
|
}
|
|
88
|
+
/** Result of a persistent-device reachability check without opening a Session. */
|
|
89
|
+
interface DeviceProbeResult {
|
|
90
|
+
readonly deviceId: string;
|
|
91
|
+
readonly deviceExpiresAt: number;
|
|
92
|
+
}
|
|
93
|
+
/** Why a short-lived Session ended; only device revocation is sent to clients. */
|
|
94
|
+
type SessionEndReason = 'logout' | 'expired' | 'evicted' | 'revoked';
|
|
88
95
|
/** Safe device metadata returned by the loopback administration API. */
|
|
89
96
|
interface DeviceSummary {
|
|
90
97
|
readonly id: string;
|
|
@@ -139,6 +146,8 @@ declare class AccessController {
|
|
|
139
146
|
pair(sourceKey: string, token: string, label?: string): Promise<PairingResult>;
|
|
140
147
|
/** Exchange a valid persistent device credential for a new short Session. */
|
|
141
148
|
renew(deviceToken: string): Promise<RenewalResult>;
|
|
149
|
+
/** Validate a persistent device credential without consuming a Session slot. */
|
|
150
|
+
probe(deviceToken: string): Promise<DeviceProbeResult>;
|
|
142
151
|
/** Resolve a short Session Cookie without revealing whether device or Session failed. */
|
|
143
152
|
authorizeSession(sessionToken: string): SessionAuthorization;
|
|
144
153
|
/** Require the Session-bound anti-CSRF value for an authenticated mutation. */
|
|
@@ -157,7 +166,7 @@ declare class AccessController {
|
|
|
157
166
|
expiresAt?: number;
|
|
158
167
|
};
|
|
159
168
|
/** Subscribe gateway resources to Session logout, expiry, eviction, and device revocation. */
|
|
160
|
-
onSessionEnded(listener: (authorization: SessionAuthorization) => void): () => void;
|
|
169
|
+
onSessionEnded(listener: (authorization: SessionAuthorization, reason: SessionEndReason) => void): () => void;
|
|
161
170
|
/** Stop new operations, drain durable mutations, then clear volatile credentials. */
|
|
162
171
|
close(): Promise<void>;
|
|
163
172
|
private finishClose;
|
|
@@ -598,6 +607,9 @@ declare class MobileAccessGateway {
|
|
|
598
607
|
private readonly mobileBootBatches;
|
|
599
608
|
private readonly extensionEventListeners;
|
|
600
609
|
private extensionEventRevision;
|
|
610
|
+
private readonly taskEventListeners;
|
|
611
|
+
private readonly deviceEventListeners;
|
|
612
|
+
private readonly pendingDeviceRevocations;
|
|
601
613
|
private extensionChangeTimer;
|
|
602
614
|
private extensionChangeTask;
|
|
603
615
|
private legacyCustomDigest;
|
|
@@ -612,6 +624,7 @@ declare class MobileAccessGateway {
|
|
|
612
624
|
private readonly removeSessionListener;
|
|
613
625
|
private readonly removeExtensionContentListener;
|
|
614
626
|
private readonly renewLimiter;
|
|
627
|
+
private readonly probeLimiter;
|
|
615
628
|
constructor(config: ResolvedGatewayConfig, store: DeviceStore, extensions?: MobileAccessService | undefined, upstreamAuthenticatedUrl?: string | undefined, extraWebSocketPaths?: {
|
|
616
629
|
has(pathname: string): boolean;
|
|
617
630
|
} | undefined, blockedUpgradeLog?: BlockedUpgradePathLog | undefined);
|
|
@@ -635,6 +648,7 @@ declare class MobileAccessGateway {
|
|
|
635
648
|
private handleRenew;
|
|
636
649
|
private handleNativePair;
|
|
637
650
|
private handleNativeRenew;
|
|
651
|
+
private handleNativeProbe;
|
|
638
652
|
private handleLogout;
|
|
639
653
|
private handleExternalRequest;
|
|
640
654
|
private handleExtensionRequest;
|
|
@@ -664,6 +678,13 @@ declare class MobileAccessGateway {
|
|
|
664
678
|
private proxyHttp;
|
|
665
679
|
private abortSessionResources;
|
|
666
680
|
private broadcastExtensionChange;
|
|
681
|
+
/** Fan a completed task to every phone holding this gateway's event stream. */
|
|
682
|
+
broadcastTaskEvent(event: {
|
|
683
|
+
readonly sessionId: string;
|
|
684
|
+
readonly turn: number;
|
|
685
|
+
}): void;
|
|
686
|
+
/** Notify only the device whose persistent credential was revoked by the Host. */
|
|
687
|
+
private broadcastDeviceRevoked;
|
|
667
688
|
private pollLegacyCustomChanges;
|
|
668
689
|
private openExtensionEventStream;
|
|
669
690
|
private readUpgradeResponse;
|
|
@@ -934,6 +955,69 @@ declare class FrpController implements RemoteProviderController {
|
|
|
934
955
|
private stopProcessAndGateway;
|
|
935
956
|
}
|
|
936
957
|
//#endregion
|
|
958
|
+
//#region src/task-events.d.ts
|
|
959
|
+
/**
|
|
960
|
+
* Host-side task-completion fan-out for phone notifications.
|
|
961
|
+
*
|
|
962
|
+
* The exact moment a run ends is known only on the Host (the phone page can
|
|
963
|
+
* merely infer it from UI state), so this module watches the public
|
|
964
|
+
* `session/event` bus for completed root turns and hands them to a hub that
|
|
965
|
+
* fans out to every live mobile gateway. Phones render the text locally, so
|
|
966
|
+
* no user content crosses this boundary — only opaque session and turn ids.
|
|
967
|
+
*/
|
|
968
|
+
/** A completed root turn worth announcing on paired phones. */
|
|
969
|
+
interface TaskCompletionEvent {
|
|
970
|
+
readonly sessionId: string;
|
|
971
|
+
readonly turn: number;
|
|
972
|
+
}
|
|
973
|
+
/** Minimal session shape read off the `session/event` bus. */
|
|
974
|
+
interface TaskEventSession {
|
|
975
|
+
readonly id: unknown;
|
|
976
|
+
readonly header?: {
|
|
977
|
+
readonly parentSession?: unknown;
|
|
978
|
+
} | null | undefined;
|
|
979
|
+
}
|
|
980
|
+
/**
|
|
981
|
+
* Minimal turn event shape read off the `session/event` bus. Fields stay
|
|
982
|
+
* unknown here and are validated at runtime below so this module never
|
|
983
|
+
* depends on the harness session packages.
|
|
984
|
+
*/
|
|
985
|
+
interface TaskTurnEvent {
|
|
986
|
+
readonly type: string;
|
|
987
|
+
readonly data?: unknown;
|
|
988
|
+
}
|
|
989
|
+
/** Structural slice of the Host context this module needs (keeps tests cordis-free). */
|
|
990
|
+
interface TaskEventContext {
|
|
991
|
+
on(event: 'session/event', handler: (session: TaskEventSession, event: TaskTurnEvent) => void): () => void;
|
|
992
|
+
}
|
|
993
|
+
interface TaskEventWatcherOptions {
|
|
994
|
+
/** Trailing debounce per session that merges turn-boundary bursts. */
|
|
995
|
+
readonly debounceMs?: number;
|
|
996
|
+
readonly onTaskCompleted: (event: TaskCompletionEvent) => void;
|
|
997
|
+
readonly log?: (event: string, fields: Readonly<Record<string, string | number | boolean>>) => void;
|
|
998
|
+
}
|
|
999
|
+
declare const TASK_EVENT_DEBOUNCE_MS = 1000;
|
|
1000
|
+
/**
|
|
1001
|
+
* Subscribe to completed root turns. Subagent turns are skipped so one task
|
|
1002
|
+
* announces once, and rapid turn boundaries collapse into a single event.
|
|
1003
|
+
* Returns a disposer that also drops pending debounces.
|
|
1004
|
+
*/
|
|
1005
|
+
declare function watchTaskCompletions(ctx: TaskEventContext, options: TaskEventWatcherOptions): () => void;
|
|
1006
|
+
/** Receives fanned-out completion events (normally a mobile gateway). */
|
|
1007
|
+
interface TaskEventSink {
|
|
1008
|
+
broadcastTaskEvent(event: TaskCompletionEvent): void;
|
|
1009
|
+
}
|
|
1010
|
+
/** One subscription feeding every live gateway; gateways register on start. */
|
|
1011
|
+
declare class TaskEventHub {
|
|
1012
|
+
private readonly sinks;
|
|
1013
|
+
/** Register a sink; returns its disposer. */
|
|
1014
|
+
add(sink: TaskEventSink): () => void;
|
|
1015
|
+
/** Fan out to a snapshot so a failing sink cannot break its siblings. */
|
|
1016
|
+
broadcast(event: TaskCompletionEvent): void;
|
|
1017
|
+
/** Visible for tests. */
|
|
1018
|
+
get size(): number;
|
|
1019
|
+
}
|
|
1020
|
+
//#endregion
|
|
937
1021
|
//#region src/plugin.d.ts
|
|
938
1022
|
/** Stable Cordis plugin name. */
|
|
939
1023
|
declare const name = "dsh-mobile";
|
|
@@ -942,5 +1026,5 @@ declare const inject: string[];
|
|
|
942
1026
|
/** Mount the resident control route and its optional authenticated LAN gateway. */
|
|
943
1027
|
declare function apply(ctx: Context, config: PluginConfig): Promise<void>;
|
|
944
1028
|
//#endregion
|
|
945
|
-
export { AUTH_PREFIX, AccessController, type AccessControllerOptions, AccessError, type AuthoritySpec, type BlockedUpgradePathEntry, BlockedUpgradePathLog, BoundedRateLimiter, CSRF_COOKIE, CSRF_HEADER, Config, FRP_VHOST_HTTP_PORT as DEFAULT_VHOST_HTTP_PORT, FRP_VHOST_HTTP_PORT, DEVICE_COOKIE, type DeviceSnapshot, type DeviceStore, type DeviceSummary, type DisabledTlsConfig, EXTENSION_LIMITS, FRP_CADDY_IMPORT_LINE, FRP_CADDY_SNIPPET_MARKER, FRP_CADDY_SNIPPET_PATH, FRP_COMPONENT_RELEASES, FrpComponentManager, type FrpComponentStatus, FrpConfigStore, type FrpConfigurationStatus, FrpController, type FrpControllerOptions, type FrpSettings, type FrpState, type FrpStatus, JsonDeviceStore, JsonMobileAccessControlStore, JsonRemoteProviderStore, LOCAL_ADMIN_PREFIX, type LocalExtensionManifest, MAX_BLOCKED_UPGRADE_PATHS, MAX_EXTRA_WEBSOCKET_PATHS, MAX_WEBSOCKET_PATH_LENGTH, MemoryDeviceStore, type MobileAccessControlState, type MobileAccessControlStore, MobileAccessGateway, MobileAccessGatewayController, type MobileAccessService as MobileAccessRegistry, MobileAccessService, type MobileAccessRuntime, type MobileActionContext, type MobileExtensionClientEntry, type MobileExtensionDefinition, MobileExtensionError, type MobileExtensionManifest, type MobileExtensionStatus, type MobileHostAction, type MobileHostRoute, type MobileRouteRequest, type MobileRouteResponse, type PairingResult, type ParsedCidr, type PluginConfig, type ProvidedTlsConfig, type RemoteProvider, type RemoteProviderController, type RemoteProviderState, type RemoteProviderStatus, type RenewalResult, RequestTrustPolicy, type ResolvedGatewayConfig, SESSION_COOKIE, type SessionAuthorization, type StoredDevice, type TlsConfig, WS_PATHS, WebSocketPathStore, addressAllowed, apply, assertExtensionId, configuredRemoteProvider, createCaddySite, createFrpServerTemplate, createFrpcToml, createMobileAccessService, createRestrictedFrpServerTemplate, inject, isGloballyRoutableIpv4, isLoopbackAddress, mergeSavedFrpSettings, mergeSavedFrpTarget, name, normalizeWebSocketPaths, parseAuthority, parseCidr, parseControlFile, parseDeviceSnapshot, parseExtensionManifest, parseFrpSettings, parseGatewayConfig, parseMobileAccessControlState, parseRemoteProviderState, resolveAuthority, rewriteMobileIndex, validateFrpPublicOrigin, validateFrpServerAddress, validateFrpServerPort, validateFrpToken, validateWebSocketPath };
|
|
1029
|
+
export { AUTH_PREFIX, AccessController, type AccessControllerOptions, AccessError, type AuthoritySpec, type BlockedUpgradePathEntry, BlockedUpgradePathLog, BoundedRateLimiter, CSRF_COOKIE, CSRF_HEADER, Config, FRP_VHOST_HTTP_PORT as DEFAULT_VHOST_HTTP_PORT, FRP_VHOST_HTTP_PORT, DEVICE_COOKIE, type DeviceProbeResult, type DeviceSnapshot, type DeviceStore, type DeviceSummary, type DisabledTlsConfig, EXTENSION_LIMITS, FRP_CADDY_IMPORT_LINE, FRP_CADDY_SNIPPET_MARKER, FRP_CADDY_SNIPPET_PATH, FRP_COMPONENT_RELEASES, FrpComponentManager, type FrpComponentStatus, FrpConfigStore, type FrpConfigurationStatus, FrpController, type FrpControllerOptions, type FrpSettings, type FrpState, type FrpStatus, JsonDeviceStore, JsonMobileAccessControlStore, JsonRemoteProviderStore, LOCAL_ADMIN_PREFIX, type LocalExtensionManifest, MAX_BLOCKED_UPGRADE_PATHS, MAX_EXTRA_WEBSOCKET_PATHS, MAX_WEBSOCKET_PATH_LENGTH, MemoryDeviceStore, type MobileAccessControlState, type MobileAccessControlStore, MobileAccessGateway, MobileAccessGatewayController, type MobileAccessService as MobileAccessRegistry, MobileAccessService, type MobileAccessRuntime, type MobileActionContext, type MobileExtensionClientEntry, type MobileExtensionDefinition, MobileExtensionError, type MobileExtensionManifest, type MobileExtensionStatus, type MobileHostAction, type MobileHostRoute, type MobileRouteRequest, type MobileRouteResponse, type PairingResult, type ParsedCidr, type PluginConfig, type ProvidedTlsConfig, type RemoteProvider, type RemoteProviderController, type RemoteProviderState, type RemoteProviderStatus, type RenewalResult, RequestTrustPolicy, type ResolvedGatewayConfig, SESSION_COOKIE, type SessionAuthorization, type SessionEndReason, type StoredDevice, TASK_EVENT_DEBOUNCE_MS, type TaskCompletionEvent, type TaskEventContext, TaskEventHub, type TaskEventSession, type TaskEventSink, type TaskEventWatcherOptions, type TaskTurnEvent, type TlsConfig, WS_PATHS, WebSocketPathStore, addressAllowed, apply, assertExtensionId, configuredRemoteProvider, createCaddySite, createFrpServerTemplate, createFrpcToml, createMobileAccessService, createRestrictedFrpServerTemplate, inject, isGloballyRoutableIpv4, isLoopbackAddress, mergeSavedFrpSettings, mergeSavedFrpTarget, name, normalizeWebSocketPaths, parseAuthority, parseCidr, parseControlFile, parseDeviceSnapshot, parseExtensionManifest, parseFrpSettings, parseGatewayConfig, parseMobileAccessControlState, parseRemoteProviderState, resolveAuthority, rewriteMobileIndex, validateFrpPublicOrigin, validateFrpServerAddress, validateFrpServerPort, validateFrpToken, validateWebSocketPath, watchTaskCompletions };
|
|
946
1030
|
//# sourceMappingURL=index.d.mts.map
|