dsh-mobile 0.4.1 → 0.4.3
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 -4
- package/README.en.md +59 -25
- package/README.md +57 -25
- package/THIRD_PARTY_NOTICES.md +29 -0
- package/bin/dsh-mobile-funnel-linux-arm64 +0 -0
- package/bin/dsh-mobile-funnel-linux-x64 +0 -0
- package/docs/CLOUDFLARE_TUNNEL.en.md +113 -0
- package/docs/CLOUDFLARE_TUNNEL.md +113 -0
- package/docs/README.md +25 -0
- package/docs/SELF_HOSTED_FRP.en.md +2 -0
- package/docs/SELF_HOSTED_ORIGIN.en.md +34 -0
- package/docs/SELF_HOSTED_ORIGIN.md +85 -0
- package/lib/cli.js.map +1 -1
- package/lib/client.js +1124 -101
- package/lib/client.js.map +1 -1
- package/lib/index.d.mts +400 -3
- package/lib/index.mjs +2129 -237
- package/lib/index.mjs.map +1 -1
- package/lib/mobile-compat.js +2 -0
- package/lib/mobile-compat.js.map +1 -0
- package/package.json +17 -7
package/lib/index.d.mts
CHANGED
|
@@ -12,6 +12,7 @@ interface StoredDevice {
|
|
|
12
12
|
readonly createdAt: number;
|
|
13
13
|
readonly expiresAt: number;
|
|
14
14
|
readonly lastSeenAt: number;
|
|
15
|
+
/** Legacy tombstone accepted on load; AccessController removes it during initialization. */
|
|
15
16
|
readonly revokedAt?: number;
|
|
16
17
|
}
|
|
17
18
|
/** Versioned device state. Raw device and Session credentials are never members. */
|
|
@@ -154,7 +155,7 @@ declare class AccessController {
|
|
|
154
155
|
assertCsrf(authorization: SessionAuthorization, csrfToken: string | undefined): void;
|
|
155
156
|
/** End one short Session and notify the gateway to abort its attached work. */
|
|
156
157
|
logout(authorization: SessionAuthorization): void;
|
|
157
|
-
/**
|
|
158
|
+
/** Durably delete the device, then end every Session owned by that device. */
|
|
158
159
|
revokeDevice(deviceId: string): Promise<boolean>;
|
|
159
160
|
/** Remove every persistent credential and terminate every active Session. */
|
|
160
161
|
resetDevices(): Promise<void>;
|
|
@@ -258,6 +259,8 @@ interface PluginConfig {
|
|
|
258
259
|
customScriptFile?: string;
|
|
259
260
|
/** Internal dedicated mobile layout browser bundle. */
|
|
260
261
|
mobileLayoutFile?: string;
|
|
262
|
+
/** Standalone browser compatibility bundle used before DSH boot. */
|
|
263
|
+
mobileCompatibilityFile?: string;
|
|
261
264
|
/** Stable public discovery identifier; it is not an authentication secret. */
|
|
262
265
|
instanceId?: string;
|
|
263
266
|
/** Managed CA certificate offered to the Android installer after fingerprint binding. */
|
|
@@ -297,6 +300,7 @@ interface ResolvedGatewayConfig {
|
|
|
297
300
|
readonly customCssFile: string;
|
|
298
301
|
readonly customScriptFile: string;
|
|
299
302
|
readonly mobileLayoutFile: string;
|
|
303
|
+
readonly mobileCompatibilityFile: string;
|
|
300
304
|
readonly instanceId: string;
|
|
301
305
|
readonly pairingCaFile?: string;
|
|
302
306
|
readonly tls: TlsConfig;
|
|
@@ -600,6 +604,15 @@ declare class MobileAccessGateway {
|
|
|
600
604
|
private server;
|
|
601
605
|
private discoverySocket;
|
|
602
606
|
private discoveryTimer;
|
|
607
|
+
/**
|
|
608
|
+
* Why broadcast discovery is unavailable, if it is. Windows keeps separate TCP and
|
|
609
|
+
* UDP port-exclusion tables, so the port the OS handed the TCP listener can be
|
|
610
|
+
* refused for UDP. That degradation is survivable but must stay observable: without
|
|
611
|
+
* it, "the phone cannot find this computer" has no diagnosable cause on the host.
|
|
612
|
+
*/
|
|
613
|
+
private discoveryError;
|
|
614
|
+
/** Names of the bundled mobile assets that could not be read, if any. */
|
|
615
|
+
private mobileAssetError;
|
|
603
616
|
private bonjour;
|
|
604
617
|
private pairingCaCertificate;
|
|
605
618
|
private listenerPort;
|
|
@@ -607,6 +620,8 @@ declare class MobileAccessGateway {
|
|
|
607
620
|
private readonly activeRequests;
|
|
608
621
|
private readonly activeWebSockets;
|
|
609
622
|
private readonly mobileBootBatches;
|
|
623
|
+
/** Cached upstream bundle byte sizes (HEAD probes), keyed by resource URL. */
|
|
624
|
+
private readonly bootEntrySizeCache;
|
|
610
625
|
private readonly extensionEventListeners;
|
|
611
626
|
private extensionEventRevision;
|
|
612
627
|
private readonly taskEventListeners;
|
|
@@ -642,6 +657,19 @@ declare class MobileAccessGateway {
|
|
|
642
657
|
port: number;
|
|
643
658
|
origin: string;
|
|
644
659
|
};
|
|
660
|
+
/**
|
|
661
|
+
* Report which discovery channels this gateway actually owns.
|
|
662
|
+
*
|
|
663
|
+
* Broadcast discovery degrades on its own when its UDP port cannot be bound, so
|
|
664
|
+
* callers need to tell "discovery is off" from "discovery was never attempted".
|
|
665
|
+
* mDNS is published independently and is unaffected by that failure.
|
|
666
|
+
*/
|
|
667
|
+
discoveryStatus(): {
|
|
668
|
+
readonly broadcast: boolean;
|
|
669
|
+
readonly mdns: boolean;
|
|
670
|
+
readonly errorCode?: string;
|
|
671
|
+
readonly mobileAssetsErrorCode?: string;
|
|
672
|
+
};
|
|
645
673
|
private requirePolicy;
|
|
646
674
|
private authorize;
|
|
647
675
|
private requireCsrf;
|
|
@@ -660,6 +688,20 @@ declare class MobileAccessGateway {
|
|
|
660
688
|
private exchangeUpstreamCookie;
|
|
661
689
|
private proxyMobileIndex;
|
|
662
690
|
private rememberMobileBootBatch;
|
|
691
|
+
/**
|
|
692
|
+
* Determine which layout-batch entries can share a merged boot batch and which
|
|
693
|
+
* must pass through. An entry at or above the per-entry cap, or one whose size
|
|
694
|
+
* could not be probed, keeps its own upstream `/plugins` row: a merged batch
|
|
695
|
+
* cannot carry it, and an unknown bundle must not risk the whole batch.
|
|
696
|
+
*/
|
|
697
|
+
private resolveMobileBootSizes;
|
|
698
|
+
/**
|
|
699
|
+
* Measure one upstream bundle by reading its body. The upstream serves
|
|
700
|
+
* `/plugins` bundles as chunked streams without a Content-Length, so a probe
|
|
701
|
+
* counts bytes; it aborts instantly past the per-entry cap. Measurements are
|
|
702
|
+
* cached for a short window.
|
|
703
|
+
*/
|
|
704
|
+
private upstreamBundleSize;
|
|
663
705
|
private serveMobileBootBatch;
|
|
664
706
|
private startMobileBootBatchAssembly;
|
|
665
707
|
private assembleMobileBootBatch;
|
|
@@ -677,7 +719,14 @@ declare class MobileAccessGateway {
|
|
|
677
719
|
private readUpstreamClientBundleWithRetry;
|
|
678
720
|
private readUpstreamClientBundle;
|
|
679
721
|
private allocateRequest;
|
|
722
|
+
/**
|
|
723
|
+
* Proxy one request upstream. Pass-through client bundles (`GET /plugins`)
|
|
724
|
+
* receive bounded transient retries — the upstream resets a fraction of fresh
|
|
725
|
+
* connections — matching the resilience the merged-batch assembly already has.
|
|
726
|
+
* A request is only retried before any byte reached the client.
|
|
727
|
+
*/
|
|
680
728
|
private proxyHttp;
|
|
729
|
+
private proxyHttpOnce;
|
|
681
730
|
private abortSessionResources;
|
|
682
731
|
private broadcastExtensionChange;
|
|
683
732
|
/** Fan a completed task to every phone holding this gateway's event stream. */
|
|
@@ -858,12 +907,13 @@ declare class FrpConfigStore {
|
|
|
858
907
|
//#endregion
|
|
859
908
|
//#region src/remote.d.ts
|
|
860
909
|
/** Remote transports supported by the desktop plugin and Android client. */
|
|
861
|
-
type RemoteProvider = 'tailscale' | 'cpolar' | 'frp';
|
|
910
|
+
type RemoteProvider = 'tailscale' | 'cpolar' | 'cloudflared' | 'frp' | 'origin';
|
|
862
911
|
/** Common safe status returned by every remote provider controller. */
|
|
863
912
|
interface RemoteProviderStatus {
|
|
864
913
|
readonly enabled: boolean;
|
|
865
914
|
readonly state: string;
|
|
866
915
|
readonly origin?: string;
|
|
916
|
+
readonly backendOrigin?: string;
|
|
867
917
|
readonly loginUrl?: string;
|
|
868
918
|
readonly setupUrl?: string;
|
|
869
919
|
readonly errorCode?: string;
|
|
@@ -883,6 +933,7 @@ interface RemoteProviderState {
|
|
|
883
933
|
readonly version: 1;
|
|
884
934
|
readonly provider: RemoteProvider;
|
|
885
935
|
}
|
|
936
|
+
declare const REMOTE_PROVIDERS: readonly RemoteProvider[];
|
|
886
937
|
/** Validate the provider selection loaded across the filesystem boundary. */
|
|
887
938
|
declare function parseRemoteProviderState(value: unknown): RemoteProviderState;
|
|
888
939
|
/** Atomic selection store whose absent-file state uses the configured default. */
|
|
@@ -957,6 +1008,350 @@ declare class FrpController implements RemoteProviderController {
|
|
|
957
1008
|
private stopProcessAndGateway;
|
|
958
1009
|
}
|
|
959
1010
|
//#endregion
|
|
1011
|
+
//#region src/origin-proxy-config.d.ts
|
|
1012
|
+
declare const DEFAULT_ORIGIN_LISTEN_PORT = 3444;
|
|
1013
|
+
/** A private HTTP listener behind a user-managed HTTPS reverse proxy. */
|
|
1014
|
+
interface OriginSettings {
|
|
1015
|
+
readonly version: 1;
|
|
1016
|
+
readonly publicOrigin: string;
|
|
1017
|
+
readonly listenHost: string;
|
|
1018
|
+
readonly listenPort: number;
|
|
1019
|
+
readonly allowedCidrs: readonly string[];
|
|
1020
|
+
}
|
|
1021
|
+
/** Configuration metadata returned only to the local desktop control UI. */
|
|
1022
|
+
interface OriginConfigurationStatus {
|
|
1023
|
+
readonly configured: boolean;
|
|
1024
|
+
readonly publicOrigin?: string;
|
|
1025
|
+
readonly listenHost?: string;
|
|
1026
|
+
readonly listenPort?: number;
|
|
1027
|
+
readonly allowedCidrs?: readonly string[];
|
|
1028
|
+
readonly backendOrigin?: string;
|
|
1029
|
+
readonly storagePath: string;
|
|
1030
|
+
readonly errorCode?: string;
|
|
1031
|
+
}
|
|
1032
|
+
/** Require a public HTTPS origin; custom external ports are supported. */
|
|
1033
|
+
declare function validateOriginPublicOrigin(value: unknown): string;
|
|
1034
|
+
/** Bind only one explicit loopback or RFC1918 IPv4 interface, never all interfaces. */
|
|
1035
|
+
declare function validateOriginListenHost(value: unknown): string;
|
|
1036
|
+
declare function validateOriginListenPort(value: unknown): number;
|
|
1037
|
+
/** Authorize direct proxy socket peers, not untrusted forwarded client headers. */
|
|
1038
|
+
declare function validateOriginAllowedCidrs(value: unknown, listenHost: string): readonly string[];
|
|
1039
|
+
/** Validate both saved settings and local administrative requests. */
|
|
1040
|
+
declare function parseOriginSettings(value: unknown): OriginSettings;
|
|
1041
|
+
/** Owns only origin settings; shared paired-device storage is never removed. */
|
|
1042
|
+
declare class OriginConfigStore {
|
|
1043
|
+
readonly stateRoot: string;
|
|
1044
|
+
readonly settingsFile: string;
|
|
1045
|
+
private settingsValue;
|
|
1046
|
+
private errorCode;
|
|
1047
|
+
constructor(stateDirectory: string);
|
|
1048
|
+
initialize(): Promise<void>;
|
|
1049
|
+
status(): OriginConfigurationStatus;
|
|
1050
|
+
settings(): OriginSettings | undefined;
|
|
1051
|
+
configure(value: unknown): Promise<OriginConfigurationStatus>;
|
|
1052
|
+
purge(): Promise<OriginConfigurationStatus>;
|
|
1053
|
+
}
|
|
1054
|
+
//#endregion
|
|
1055
|
+
//#region src/origin-proxy.d.ts
|
|
1056
|
+
type OriginState = 'off' | 'unavailable' | 'starting' | 'ready' | 'error';
|
|
1057
|
+
/** Ready means the private listener is ready, not that public ingress was tested. */
|
|
1058
|
+
interface OriginStatus {
|
|
1059
|
+
readonly enabled: boolean;
|
|
1060
|
+
readonly state: OriginState;
|
|
1061
|
+
readonly origin?: string;
|
|
1062
|
+
readonly backendOrigin?: string;
|
|
1063
|
+
readonly errorCode?: string;
|
|
1064
|
+
}
|
|
1065
|
+
interface OriginControllerOptions {
|
|
1066
|
+
readonly store: MobileAccessControlStore;
|
|
1067
|
+
readonly config: OriginConfigStore;
|
|
1068
|
+
readonly createGateway: (settings: OriginSettings) => Promise<MobileAccessGateway>;
|
|
1069
|
+
readonly onStatus?: (status: OriginStatus) => void;
|
|
1070
|
+
}
|
|
1071
|
+
/** Owns an authenticated HTTP gateway, with no tunnel process or public network probes. */
|
|
1072
|
+
declare class OriginController implements RemoteProviderController {
|
|
1073
|
+
private readonly options;
|
|
1074
|
+
private enabled;
|
|
1075
|
+
private initialized;
|
|
1076
|
+
private disposed;
|
|
1077
|
+
private gatewayValue;
|
|
1078
|
+
private latest;
|
|
1079
|
+
private queue;
|
|
1080
|
+
constructor(options: OriginControllerOptions);
|
|
1081
|
+
initialize(): Promise<void>;
|
|
1082
|
+
gateway(): MobileAccessGateway | undefined;
|
|
1083
|
+
status(): OriginStatus;
|
|
1084
|
+
setEnabled(enabled: boolean): Promise<OriginStatus>;
|
|
1085
|
+
reconnect(): Promise<OriginStatus>;
|
|
1086
|
+
/** Reset the switch, retaining both settings and shared remote device pairings. */
|
|
1087
|
+
reset(): Promise<OriginStatus>;
|
|
1088
|
+
/** Stop the listener without changing the durable switch. */
|
|
1089
|
+
close(): Promise<void>;
|
|
1090
|
+
private assertAvailable;
|
|
1091
|
+
private enqueue;
|
|
1092
|
+
private publish;
|
|
1093
|
+
private start;
|
|
1094
|
+
private stop;
|
|
1095
|
+
}
|
|
1096
|
+
//#endregion
|
|
1097
|
+
//#region src/cloudflared-component.d.ts
|
|
1098
|
+
/**
|
|
1099
|
+
* Pinned cloudflared components fetched only after an explicit user action.
|
|
1100
|
+
*
|
|
1101
|
+
* Unlike the cpolar archive each artifact IS the executable: there is nothing
|
|
1102
|
+
* to unpack, so the download digest and the installed digest are the same pair.
|
|
1103
|
+
* `--no-autoupdate` is passed at runtime as well, so the pinned bytes stay the
|
|
1104
|
+
* bytes that were verified.
|
|
1105
|
+
*/
|
|
1106
|
+
interface CloudflaredArtifact {
|
|
1107
|
+
readonly version: string;
|
|
1108
|
+
readonly platform: NodeJS.Platform;
|
|
1109
|
+
readonly arch: string;
|
|
1110
|
+
readonly downloadUrl: string;
|
|
1111
|
+
readonly downloadBytes: number;
|
|
1112
|
+
readonly downloadSha256: string;
|
|
1113
|
+
readonly executableName: string;
|
|
1114
|
+
}
|
|
1115
|
+
/**
|
|
1116
|
+
* Canonical release metadata. New code should select from
|
|
1117
|
+
* {@link CLOUDFLARED_COMPONENT_RELEASES} by platform and architecture; this
|
|
1118
|
+
* alias preserves the original Windows x64 entry for existing callers.
|
|
1119
|
+
*/
|
|
1120
|
+
declare const CLOUDFLARED_COMPONENT_RELEASE: CloudflaredArtifact;
|
|
1121
|
+
/**
|
|
1122
|
+
* Public, credential-free description of the managed cloudflared component.
|
|
1123
|
+
*
|
|
1124
|
+
* There is deliberately no `configured` flag: a quick tunnel needs no account,
|
|
1125
|
+
* token, or DNS record, so installation is the only precondition.
|
|
1126
|
+
*/
|
|
1127
|
+
interface CloudflaredComponentStatus {
|
|
1128
|
+
readonly supported: boolean;
|
|
1129
|
+
readonly installed: boolean;
|
|
1130
|
+
readonly version: string;
|
|
1131
|
+
readonly downloadBytes: number;
|
|
1132
|
+
readonly installedBytes: number;
|
|
1133
|
+
readonly sourceUrl: string;
|
|
1134
|
+
readonly downloadPage: string;
|
|
1135
|
+
readonly termsUrl: string;
|
|
1136
|
+
readonly storagePath: string;
|
|
1137
|
+
readonly errorCode?: string;
|
|
1138
|
+
}
|
|
1139
|
+
interface CloudflaredComponentManagerOptions {
|
|
1140
|
+
readonly stateDirectory: string;
|
|
1141
|
+
readonly platform?: NodeJS.Platform;
|
|
1142
|
+
readonly arch?: string;
|
|
1143
|
+
readonly fetchArtifact?: (url: string, signal: AbortSignal) => Promise<Uint8Array>;
|
|
1144
|
+
}
|
|
1145
|
+
/** Owns the optional cloudflared binary inside DSH Mobile state. */
|
|
1146
|
+
declare class CloudflaredComponentManager {
|
|
1147
|
+
readonly executable: string;
|
|
1148
|
+
readonly componentRoot: string;
|
|
1149
|
+
readonly componentStorage: string;
|
|
1150
|
+
readonly stateRoot: string;
|
|
1151
|
+
readonly logRoot: string;
|
|
1152
|
+
private readonly stagingRoot;
|
|
1153
|
+
private readonly platform;
|
|
1154
|
+
private readonly arch;
|
|
1155
|
+
private readonly release;
|
|
1156
|
+
private readonly fetchArtifact;
|
|
1157
|
+
private installed;
|
|
1158
|
+
private errorCode;
|
|
1159
|
+
private queue;
|
|
1160
|
+
constructor(options: CloudflaredComponentManagerOptions);
|
|
1161
|
+
/** Inspect the managed binary without using any global cloudflared state. */
|
|
1162
|
+
initialize(): Promise<void>;
|
|
1163
|
+
/** Return a safe status that never includes machine-specific account data. */
|
|
1164
|
+
status(): CloudflaredComponentStatus;
|
|
1165
|
+
/** Download, verify, and install the pinned cloudflared executable after explicit confirmation. */
|
|
1166
|
+
install(): Promise<CloudflaredComponentStatus>;
|
|
1167
|
+
/** Remove every cloudflared file owned by DSH Mobile without touching global state. */
|
|
1168
|
+
purge(): Promise<CloudflaredComponentStatus>;
|
|
1169
|
+
private enqueue;
|
|
1170
|
+
}
|
|
1171
|
+
//#endregion
|
|
1172
|
+
//#region src/cloudflared-tunnel.d.ts
|
|
1173
|
+
/** Which tunnel flavour the cloudflared provider runs. */
|
|
1174
|
+
type CloudflaredTunnelMode = 'quick' | 'named';
|
|
1175
|
+
/**
|
|
1176
|
+
* Cloudflared provider configuration.
|
|
1177
|
+
*
|
|
1178
|
+
* A quick tunnel owns nothing durable: cloudflared allocates a random hostname
|
|
1179
|
+
* and a random forward port every start. A named tunnel instead runs with an
|
|
1180
|
+
* account token, and its public hostname is routed by Cloudflare to the local
|
|
1181
|
+
* port recorded here, so that port must stay stable across restarts.
|
|
1182
|
+
*/
|
|
1183
|
+
type CloudflaredTunnelSettings = {
|
|
1184
|
+
readonly version: 1;
|
|
1185
|
+
readonly mode: 'quick';
|
|
1186
|
+
} | {
|
|
1187
|
+
readonly version: 1;
|
|
1188
|
+
readonly mode: 'named';
|
|
1189
|
+
readonly token: string;
|
|
1190
|
+
readonly hostname: string;
|
|
1191
|
+
readonly port: number;
|
|
1192
|
+
};
|
|
1193
|
+
/** Configuration metadata safe to hand to the desktop panel; never the token. */
|
|
1194
|
+
interface CloudflaredTunnelStatus {
|
|
1195
|
+
readonly mode: CloudflaredTunnelMode;
|
|
1196
|
+
readonly configured: boolean;
|
|
1197
|
+
readonly hostname?: string;
|
|
1198
|
+
readonly port?: number;
|
|
1199
|
+
readonly storagePath: string;
|
|
1200
|
+
readonly errorCode?: string;
|
|
1201
|
+
}
|
|
1202
|
+
/**
|
|
1203
|
+
* Validate the public hostname Cloudflare routes to this tunnel.
|
|
1204
|
+
*
|
|
1205
|
+
* The name must be a real DNS name, not an IP literal or a wildcard, and it
|
|
1206
|
+
* cannot sit under Cloudflare's own control-plane suffixes: `trycloudflare.com`
|
|
1207
|
+
* belongs to quick tunnels, and a `cfargotunnel.com` name is the routing target
|
|
1208
|
+
* rather than a routable public address.
|
|
1209
|
+
*/
|
|
1210
|
+
declare function validateCloudflaredTunnelHostname(value: unknown): string;
|
|
1211
|
+
/** Validate the stable loopback port Cloudflare's ingress forwards to. */
|
|
1212
|
+
declare function validateCloudflaredTunnelPort(value: unknown): number;
|
|
1213
|
+
/**
|
|
1214
|
+
* Validate a connector token before durable storage.
|
|
1215
|
+
*
|
|
1216
|
+
* A token is a base64url-encoded JSON blob that carries the account, tunnel id
|
|
1217
|
+
* and tunnel secret; the provider passes it through the environment rather than
|
|
1218
|
+
* the command line, and it is never returned to any client.
|
|
1219
|
+
*/
|
|
1220
|
+
declare function validateCloudflaredTunnelToken(value: unknown): string;
|
|
1221
|
+
/** Parse tunnel settings at the request and filesystem boundaries. */
|
|
1222
|
+
declare function parseCloudflaredTunnelSettings(value: unknown): CloudflaredTunnelSettings;
|
|
1223
|
+
/**
|
|
1224
|
+
* Merge a partial panel request with the saved named-tunnel settings so a blank
|
|
1225
|
+
* field keeps its stored value. The token in particular is write-only, so the
|
|
1226
|
+
* panel submits an empty string to mean "keep the existing connector token".
|
|
1227
|
+
*/
|
|
1228
|
+
declare function mergeSavedCloudflaredTunnelSettings(partial: Readonly<Record<string, unknown>>, saved: CloudflaredTunnelSettings | undefined): CloudflaredTunnelSettings;
|
|
1229
|
+
/** Owns the private cloudflared tunnel configuration for one DSH installation. */
|
|
1230
|
+
declare class CloudflaredTunnelStore {
|
|
1231
|
+
readonly stateRoot: string;
|
|
1232
|
+
readonly settingsFile: string;
|
|
1233
|
+
private settingsValue;
|
|
1234
|
+
private errorCode;
|
|
1235
|
+
constructor(stateDirectory: string);
|
|
1236
|
+
/** Load private settings while rejecting links, oversized files and unknown fields. */
|
|
1237
|
+
initialize(): Promise<void>;
|
|
1238
|
+
/** Return configuration metadata without exposing the connector token. */
|
|
1239
|
+
status(): CloudflaredTunnelStatus;
|
|
1240
|
+
/** Return private settings only to the provider lifecycle. */
|
|
1241
|
+
settings(): CloudflaredTunnelSettings;
|
|
1242
|
+
/** Atomically replace the tunnel configuration. */
|
|
1243
|
+
configure(value: unknown): Promise<CloudflaredTunnelStatus>;
|
|
1244
|
+
/** Forget a named tunnel and its connector token. */
|
|
1245
|
+
purge(): Promise<CloudflaredTunnelStatus>;
|
|
1246
|
+
}
|
|
1247
|
+
//#endregion
|
|
1248
|
+
//#region src/cloudflared.d.ts
|
|
1249
|
+
/** Product-facing states for the optional cloudflared remote transport. */
|
|
1250
|
+
type CloudflaredState = 'off' | 'unavailable' | 'starting' | 'connecting' | 'ready' | 'error';
|
|
1251
|
+
/** Safe cloudflared state returned only through the loopback DSH control route. */
|
|
1252
|
+
interface CloudflaredStatus {
|
|
1253
|
+
readonly enabled: boolean;
|
|
1254
|
+
readonly state: CloudflaredState;
|
|
1255
|
+
readonly origin?: string;
|
|
1256
|
+
readonly errorCode?: string;
|
|
1257
|
+
}
|
|
1258
|
+
/** Inputs for one cloudflared process and its authenticated DSH gateway. */
|
|
1259
|
+
interface CloudflaredControllerOptions {
|
|
1260
|
+
readonly store: MobileAccessControlStore;
|
|
1261
|
+
readonly executable: string;
|
|
1262
|
+
/** Named-tunnel configuration; quick tunnels are used when it reports quick mode. */
|
|
1263
|
+
readonly tunnel: {
|
|
1264
|
+
settings(): CloudflaredTunnelSettings;
|
|
1265
|
+
};
|
|
1266
|
+
readonly createGateway: (origin: string, listenPort: number) => Promise<MobileAccessGateway>;
|
|
1267
|
+
readonly onStatus?: (status: CloudflaredStatus) => void;
|
|
1268
|
+
/** Liveness bound for one startup-timeout round; defaults to the product timeout. */
|
|
1269
|
+
readonly startupTimeoutMs?: number;
|
|
1270
|
+
/**
|
|
1271
|
+
* Total startup-timeout rounds before a live named connector is given up on;
|
|
1272
|
+
* defaults to NAMED_STARTUP_ROUNDS. Quick tunnels always use a single round.
|
|
1273
|
+
*/
|
|
1274
|
+
readonly maxStartupRounds?: number;
|
|
1275
|
+
readonly spawnProcess?: (executable: string, args: readonly string[], environment: NodeJS.ProcessEnv) => ChildProcessWithoutNullStreams;
|
|
1276
|
+
}
|
|
1277
|
+
/**
|
|
1278
|
+
* Extract a validated public HTTPS origin from one cloudflared output line.
|
|
1279
|
+
*
|
|
1280
|
+
* Quick tunnels print the public hostname inside a decorated banner, so the
|
|
1281
|
+
* candidate is taken from the line and then re-parsed as a URL: a lookalike such
|
|
1282
|
+
* as `https://x.trycloudflare.com.evil.test` fails the hostname check instead of
|
|
1283
|
+
* being truncated into an accepted origin.
|
|
1284
|
+
*/
|
|
1285
|
+
declare function parseCloudflaredOrigin(line: string): string | undefined;
|
|
1286
|
+
/**
|
|
1287
|
+
* Whether one cloudflared log line reports an established edge connection.
|
|
1288
|
+
*
|
|
1289
|
+
* A named tunnel prints no banner, so registration is the only signal that the
|
|
1290
|
+
* connector reached Cloudflare and the public hostname can serve traffic. Both
|
|
1291
|
+
* the current and the older wording are accepted; anything else is ignored so a
|
|
1292
|
+
* chatty log line cannot be mistaken for readiness.
|
|
1293
|
+
*/
|
|
1294
|
+
declare function isCloudflaredRegistration(line: string): boolean;
|
|
1295
|
+
/**
|
|
1296
|
+
* Owns an installed cloudflared client and a provider-specific DSH remote gateway.
|
|
1297
|
+
*
|
|
1298
|
+
* Quick tunnels allocate a random hostname and a random forward port on every
|
|
1299
|
+
* start. Named tunnels instead read an account token and a stable public
|
|
1300
|
+
* hostname from the tunnel store, forward to the configured loopback port, and
|
|
1301
|
+
* learn readiness from the connector's registration line rather than a banner.
|
|
1302
|
+
*/
|
|
1303
|
+
declare class CloudflaredController implements RemoteProviderController {
|
|
1304
|
+
private readonly options;
|
|
1305
|
+
private enabled;
|
|
1306
|
+
private initialized;
|
|
1307
|
+
private disposed;
|
|
1308
|
+
private child;
|
|
1309
|
+
private gatewayValue;
|
|
1310
|
+
private reservation;
|
|
1311
|
+
private generation;
|
|
1312
|
+
private buffer;
|
|
1313
|
+
private mode;
|
|
1314
|
+
private namedOrigin;
|
|
1315
|
+
private latest;
|
|
1316
|
+
private queue;
|
|
1317
|
+
private startupTimer;
|
|
1318
|
+
private startupRounds;
|
|
1319
|
+
constructor(options: CloudflaredControllerOptions);
|
|
1320
|
+
/** Restore the remembered cloudflared switch independently from LAN and other providers. */
|
|
1321
|
+
initialize(): Promise<void>;
|
|
1322
|
+
/** Return the active cloudflared-backed DSH gateway. */
|
|
1323
|
+
gateway(): MobileAccessGateway | undefined;
|
|
1324
|
+
/** Return state safe for the desktop control UI. */
|
|
1325
|
+
status(): CloudflaredStatus;
|
|
1326
|
+
/** Enable or disable cloudflared without changing LAN or other provider state. */
|
|
1327
|
+
setEnabled(enabled: boolean): Promise<CloudflaredStatus>;
|
|
1328
|
+
/** Restart cloudflared and allocate a fresh quick tunnel. */
|
|
1329
|
+
reconnect(): Promise<CloudflaredStatus>;
|
|
1330
|
+
/** Disable cloudflared without deleting the installed component. */
|
|
1331
|
+
reset(): Promise<CloudflaredStatus>;
|
|
1332
|
+
/** Stop owned resources without changing the remembered switch. */
|
|
1333
|
+
close(): Promise<void>;
|
|
1334
|
+
private enqueue;
|
|
1335
|
+
private publish;
|
|
1336
|
+
private start;
|
|
1337
|
+
private armStartupTimer;
|
|
1338
|
+
/**
|
|
1339
|
+
* Give a live named connector more time instead of killing it: it retries the
|
|
1340
|
+
* edge on its own and usually registers once the rebooted network is usable.
|
|
1341
|
+
* A dead connector, or an exhausted budget, fails the generation as before.
|
|
1342
|
+
*/
|
|
1343
|
+
private checkStartupTimeout;
|
|
1344
|
+
private consume;
|
|
1345
|
+
/** Mark a named tunnel ready once the connector has registered with the edge. */
|
|
1346
|
+
private confirmNamedReady;
|
|
1347
|
+
private attachGateway;
|
|
1348
|
+
/** Replace the gateway authority when a quick tunnel restarts on a new hostname. */
|
|
1349
|
+
private rotateGateway;
|
|
1350
|
+
private failGeneration;
|
|
1351
|
+
private stop;
|
|
1352
|
+
private stopProcessAndGateway;
|
|
1353
|
+
}
|
|
1354
|
+
//#endregion
|
|
960
1355
|
//#region src/task-events.d.ts
|
|
961
1356
|
/**
|
|
962
1357
|
* Host-side task-completion fan-out for phone notifications.
|
|
@@ -1025,8 +1420,10 @@ declare class TaskEventHub {
|
|
|
1025
1420
|
declare const name = "dsh-mobile";
|
|
1026
1421
|
/** The stock WebServer serves the control card; Connection authenticates the loopback DSH origin. */
|
|
1027
1422
|
declare const inject: string[];
|
|
1423
|
+
/** Reuse remote HTTPS policy while binding a separately validated private HTTP origin. */
|
|
1424
|
+
declare function originGatewayConfig(template: ResolvedGatewayConfig, settings: OriginSettings, stateFile: string, instanceId: string, listenPort?: number): ResolvedGatewayConfig;
|
|
1028
1425
|
/** Mount the resident control route and its optional authenticated LAN gateway. */
|
|
1029
1426
|
declare function apply(ctx: Context, config: PluginConfig): Promise<void>;
|
|
1030
1427
|
//#endregion
|
|
1031
|
-
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 };
|
|
1428
|
+
export { AUTH_PREFIX, AccessController, type AccessControllerOptions, AccessError, type AuthoritySpec, type BlockedUpgradePathEntry, BlockedUpgradePathLog, BoundedRateLimiter, CLOUDFLARED_COMPONENT_RELEASE, CSRF_COOKIE, CSRF_HEADER, CloudflaredComponentManager, type CloudflaredComponentStatus, CloudflaredController, type CloudflaredControllerOptions, type CloudflaredState, type CloudflaredStatus, type CloudflaredTunnelMode, type CloudflaredTunnelSettings, type CloudflaredTunnelStatus, CloudflaredTunnelStore, Config, DEFAULT_ORIGIN_LISTEN_PORT, 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, OriginConfigStore, type OriginConfigurationStatus, OriginController, type OriginControllerOptions, type OriginSettings, type OriginState, type OriginStatus, type PairingResult, type ParsedCidr, type PluginConfig, type ProvidedTlsConfig, REMOTE_PROVIDERS, 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, isCloudflaredRegistration, isGloballyRoutableIpv4, isLoopbackAddress, mergeSavedCloudflaredTunnelSettings, mergeSavedFrpSettings, mergeSavedFrpTarget, name, normalizeWebSocketPaths, originGatewayConfig, parseAuthority, parseCidr, parseCloudflaredOrigin, parseCloudflaredTunnelSettings, parseControlFile, parseDeviceSnapshot, parseExtensionManifest, parseFrpSettings, parseGatewayConfig, parseMobileAccessControlState, parseOriginSettings, parseRemoteProviderState, resolveAuthority, rewriteMobileIndex, validateCloudflaredTunnelHostname, validateCloudflaredTunnelPort, validateCloudflaredTunnelToken, validateFrpPublicOrigin, validateFrpServerAddress, validateFrpServerPort, validateFrpToken, validateOriginAllowedCidrs, validateOriginListenHost, validateOriginListenPort, validateOriginPublicOrigin, validateWebSocketPath, watchTaskCompletions };
|
|
1032
1429
|
//# sourceMappingURL=index.d.mts.map
|