-
Notifications
You must be signed in to change notification settings - Fork 877
Expand file tree
/
Copy pathconnection-config.ts
More file actions
127 lines (108 loc) · 3.73 KB
/
connection-config.ts
File metadata and controls
127 lines (108 loc) · 3.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import * as FS from "node:fs";
import * as Path from "node:path";
import type {
DesktopConnectionInfo,
DesktopConnectionMode,
DesktopConnectionSettings,
} from "@t3tools/contracts";
export class DesktopConnectionConfigError extends Error {
constructor(message: string) {
super(message);
this.name = "DesktopConnectionConfigError";
}
}
const CONNECTION_CONFIG_FILENAME = "desktop-connection.json";
export function getDefaultDesktopConnectionSettings(): DesktopConnectionSettings {
return {
mode: "local",
remoteUrl: "",
remoteAuthToken: "",
};
}
function normalizeMode(value: unknown): DesktopConnectionMode {
return value === "remote" ? "remote" : "local";
}
function normalizeString(value: unknown): string {
return typeof value === "string" ? value.trim() : "";
}
export function sanitizeDesktopConnectionSettings(value: unknown): DesktopConnectionSettings {
if (!value || typeof value !== "object") {
return getDefaultDesktopConnectionSettings();
}
const record = value as Record<string, unknown>;
return {
mode: normalizeMode(record.mode),
remoteUrl: normalizeString(record.remoteUrl),
remoteAuthToken: normalizeString(record.remoteAuthToken),
};
}
export function validateDesktopConnectionSettings(
input: DesktopConnectionSettings,
): DesktopConnectionSettings {
const settings = sanitizeDesktopConnectionSettings(input);
if (settings.mode === "local") {
return settings;
}
if (settings.remoteUrl.length === 0) {
throw new DesktopConnectionConfigError("Remote URL is required.");
}
let remoteUrl: URL;
try {
remoteUrl = new URL(settings.remoteUrl);
} catch {
throw new DesktopConnectionConfigError("Remote URL must be a valid http:// or https:// URL.");
}
if (remoteUrl.protocol !== "http:" && remoteUrl.protocol !== "https:") {
throw new DesktopConnectionConfigError("Remote URL must use http:// or https://.");
}
if (!remoteUrl.hostname) {
throw new DesktopConnectionConfigError("Remote URL must include a host.");
}
return {
...settings,
remoteUrl: remoteUrl.toString(),
};
}
export function buildDesktopRemoteWsUrl(settings: DesktopConnectionSettings): string {
const validated = validateDesktopConnectionSettings(settings);
if (validated.mode !== "remote") {
throw new DesktopConnectionConfigError("Remote WebSocket URL is only available in remote mode.");
}
const remoteUrl = new URL(validated.remoteUrl);
remoteUrl.protocol = remoteUrl.protocol === "https:" ? "wss:" : "ws:";
remoteUrl.pathname = "/";
remoteUrl.search = "";
if (validated.remoteAuthToken.length > 0) {
remoteUrl.searchParams.set("token", validated.remoteAuthToken);
}
remoteUrl.hash = "";
return remoteUrl.toString();
}
export function getDesktopConnectionInfo(
settings: DesktopConnectionSettings,
): DesktopConnectionInfo {
return { mode: settings.mode };
}
export function resolveDesktopConnectionConfigPath(userDataPath: string): string {
return Path.join(userDataPath, CONNECTION_CONFIG_FILENAME);
}
export function readDesktopConnectionSettings(configPath: string): DesktopConnectionSettings {
try {
const raw = FS.readFileSync(configPath, "utf8");
return sanitizeDesktopConnectionSettings(JSON.parse(raw));
} catch (error) {
if ((error as NodeJS.ErrnoException)?.code === "ENOENT") {
return getDefaultDesktopConnectionSettings();
}
throw error;
}
}
export function writeDesktopConnectionSettings(
configPath: string,
input: DesktopConnectionSettings,
): DesktopConnectionSettings {
const settings = validateDesktopConnectionSettings(input);
FS.mkdirSync(Path.dirname(configPath), { recursive: true });
FS.writeFileSync(configPath, JSON.stringify(settings, null, 2) + "\n", "utf8");
return settings;
}