feat: establish NekoNest Cloud control and relay
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
export type SupportedHostOS = "windows" | "linux";
|
||||
|
||||
export function assertSafeConnectOrigin(value: string): string {
|
||||
const origin = value.trim().replace(/\/$/, "");
|
||||
const parsed = new URL(origin);
|
||||
const isLoopback = ["localhost", "127.0.0.1", "[::1]"].includes(parsed.hostname);
|
||||
if (parsed.origin !== origin || (parsed.protocol !== "https:" && !(parsed.protocol === "http:" && isLoopback))) {
|
||||
throw new Error("Cloud Connect 服务必须使用 HTTPS origin(本机开发地址除外)");
|
||||
}
|
||||
return origin;
|
||||
}
|
||||
|
||||
export function resolveConnectOrigin(
|
||||
configured: string | undefined,
|
||||
development = process.env.NODE_ENV !== "production",
|
||||
): string {
|
||||
const value = configured?.trim() ?? "";
|
||||
if (value) return assertSafeConnectOrigin(value);
|
||||
if (development) return "http://127.0.0.1:3000";
|
||||
throw new Error("NEKONEST_CLOUD_CONNECT_ORIGIN is required outside development");
|
||||
}
|
||||
|
||||
export function quotePowerShell(value: string): string {
|
||||
return `'${value.replaceAll("'", "''")}'`;
|
||||
}
|
||||
|
||||
export function quoteBash(value: string): string {
|
||||
return `'${value.replaceAll("'", `'"'"'`)}'`;
|
||||
}
|
||||
|
||||
export function buildDaemonRegistrationCommand(input: {
|
||||
os: SupportedHostOS;
|
||||
connectOrigin: string;
|
||||
hostName: string;
|
||||
}): string {
|
||||
const connectOrigin = assertSafeConnectOrigin(input.connectOrigin);
|
||||
const hostName = input.hostName.trim();
|
||||
if (!hostName) throw new Error("主机名称不能为空");
|
||||
|
||||
if (input.os === "windows") {
|
||||
return [
|
||||
`$env:NEKONEST_SERVER = ${quotePowerShell(connectOrigin)}`,
|
||||
`$env:NEKONEST_TRANSPORT_MODE = 'sealed'`,
|
||||
`$secureToken = Read-Host '粘贴一次性配对码' -AsSecureString`,
|
||||
`$tokenPtr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($secureToken)`,
|
||||
"try {",
|
||||
` $env:NEKONEST_BOOTSTRAP_TOKEN = [Runtime.InteropServices.Marshal]::PtrToStringBSTR($tokenPtr)`,
|
||||
` if ([string]::IsNullOrWhiteSpace($env:NEKONEST_BOOTSTRAP_TOKEN)) { throw '未读取到配对码' }`,
|
||||
` & '.\\nekonest-daemon.exe' -register -name ${quotePowerShell(hostName)}`,
|
||||
"} finally {",
|
||||
" Remove-Item Env:NEKONEST_BOOTSTRAP_TOKEN -ErrorAction SilentlyContinue",
|
||||
" [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($tokenPtr)",
|
||||
"}",
|
||||
].join("\n");
|
||||
}
|
||||
|
||||
return [
|
||||
"(",
|
||||
" read -rsp '粘贴一次性配对码: ' NEKONEST_BOOTSTRAP_TOKEN",
|
||||
" printf '\\n'",
|
||||
` if [ -z "$NEKONEST_BOOTSTRAP_TOKEN" ]; then printf '未读取到配对码\\n' >&2; exit 1; fi`,
|
||||
` export NEKONEST_SERVER=${quoteBash(connectOrigin)}`,
|
||||
" export NEKONEST_TRANSPORT_MODE='sealed'",
|
||||
" export NEKONEST_BOOTSTRAP_TOKEN",
|
||||
` ./nekonest-daemon -register -name ${quoteBash(hostName)}`,
|
||||
")",
|
||||
].join("\n");
|
||||
}
|
||||
|
||||
export function daemonStartCommand(os: SupportedHostOS): string {
|
||||
return os === "windows" ? ".\\nekonest-daemon.exe" : "./nekonest-daemon";
|
||||
}
|
||||
Reference in New Issue
Block a user