@astralyn/sash 0.1.0 → 0.1.2

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.
Files changed (108) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/README.md +22 -7
  3. package/THIRD_PARTY_NOTICES.md +9 -0
  4. package/dist/api.js +14 -45
  5. package/dist/app-state.js +99 -0
  6. package/dist/autostart/command.js +24 -0
  7. package/dist/autostart/context.js +43 -0
  8. package/dist/autostart/files.js +60 -0
  9. package/dist/autostart/installation.js +48 -0
  10. package/dist/autostart/start.js +47 -0
  11. package/dist/autostart/windows-registry.js +88 -0
  12. package/dist/autostart/windows.js +59 -0
  13. package/dist/autostart-contract.js +31 -0
  14. package/dist/autostart-entry.js +10 -0
  15. package/dist/autostart.js +69 -0
  16. package/dist/cli.js +11 -11
  17. package/dist/commands/auto.js +15 -0
  18. package/dist/commands/lifecycle.js +5 -31
  19. package/dist/commands/logs.js +11 -4
  20. package/dist/commands/shared.js +2 -4
  21. package/dist/commands/status.js +6 -7
  22. package/dist/commands/update.js +7 -3
  23. package/dist/commands/web.js +19 -27
  24. package/dist/contracts.js +171 -335
  25. package/dist/core-config-validation.js +22 -38
  26. package/dist/core-update.js +126 -762
  27. package/dist/core.js +20 -46
  28. package/dist/daemon/app.js +132 -113
  29. package/dist/daemon/context.js +13 -7
  30. package/dist/daemon/entry.js +21 -38
  31. package/dist/daemon/errors.js +6 -1
  32. package/dist/daemon/handlers/autostart.js +18 -0
  33. package/dist/daemon/handlers/core.js +32 -9
  34. package/dist/daemon/handlers/daemon.js +32 -6
  35. package/dist/daemon/handlers/profiles.js +12 -2
  36. package/dist/daemon/handlers/settings.js +9 -36
  37. package/dist/daemon/router.js +40 -27
  38. package/dist/daemon/scheduler.js +3 -1
  39. package/dist/daemon/server.js +6 -3
  40. package/dist/daemon/web-auth.js +52 -0
  41. package/dist/daemon-auth.js +2 -2
  42. package/dist/daemon-client.js +18 -2
  43. package/dist/daemon-http.js +7 -0
  44. package/dist/daemon-lifecycle.js +19 -196
  45. package/dist/github.js +7 -2
  46. package/dist/http.js +7 -5
  47. package/dist/log-follow.js +2 -1
  48. package/dist/mihomo-config.js +7 -9
  49. package/dist/paths.js +5 -7
  50. package/dist/profile-model.js +87 -0
  51. package/dist/profile-service.js +250 -587
  52. package/dist/profiles.js +43 -171
  53. package/dist/runtime-lifecycle.js +112 -194
  54. package/dist/runtime-owner.js +37 -76
  55. package/dist/sash-client.js +63 -21
  56. package/dist/settings-service.js +29 -228
  57. package/dist/settings.js +61 -285
  58. package/dist/status.js +24 -40
  59. package/dist/supervisor.js +1 -14
  60. package/dist/sysproxy/common.js +5 -45
  61. package/dist/sysproxy/factory.js +24 -65
  62. package/dist/sysproxy/snapshot.js +24 -257
  63. package/dist/sysproxy.js +1 -4
  64. package/dist/system-proxy-manager.js +37 -35
  65. package/dist/ui/assets/{ConnectionsView-DNGmZBSU.js → ConnectionsView-BgXQM6Z4.js} +1 -1
  66. package/dist/ui/assets/{LogsView-fSiaxQ13.js → LogsView-2f542P8z.js} +1 -1
  67. package/dist/ui/assets/{PaginationFooter-B3kHzRfB.js → PaginationFooter-cj1tcZej.js} +1 -1
  68. package/dist/ui/assets/ProfileEditorDialog-C9M8uKZC.css +1 -0
  69. package/dist/ui/assets/ProfileEditorDialog-DD4y4GBC.js +14 -0
  70. package/dist/ui/assets/ProfilesView-BXU2DOA7.css +1 -0
  71. package/dist/ui/assets/ProfilesView-DNnzYIEY.js +7 -0
  72. package/dist/ui/assets/{RulesView-D9vZBiJ1.js → RulesView-CtKvlckZ.js} +1 -1
  73. package/dist/ui/assets/SettingsView-BaeKFF_N.js +1 -0
  74. package/dist/ui/assets/SettingsView-CWjIe05v.css +1 -0
  75. package/dist/ui/assets/{0be242294f7d791af850c6df38ac78a0-2cL6Ntwf.woff2 → e2a57555d97d0b02b45d9418eb6ee295-D9nhF3rM.woff2} +0 -0
  76. package/dist/ui/assets/index-CBInDvdJ.js +19 -0
  77. package/dist/ui/assets/index-mOLy7fkB.css +1 -0
  78. package/dist/ui/assets/{theme-BNq4FkXS.js → theme-D40MF8cQ.js} +1 -1
  79. package/dist/ui/index.html +2 -2
  80. package/dist/web-bootstrap.js +113 -0
  81. package/docs/architecture-proposal.md +109 -0
  82. package/docs/autostart.md +101 -0
  83. package/docs/backend.md +92 -216
  84. package/docs/frontend.md +61 -97
  85. package/docs/usage.md +88 -186
  86. package/package.json +10 -6
  87. package/dist/commands/upgrade.js +0 -43
  88. package/dist/core-install-transaction.js +0 -114
  89. package/dist/core-update-coordination.js +0 -105
  90. package/dist/core-update-service.js +0 -245
  91. package/dist/managed-state-transaction.js +0 -377
  92. package/dist/offline-mutation.js +0 -58
  93. package/dist/profile-migration.js +0 -101
  94. package/dist/runtime-recovery.js +0 -31
  95. package/dist/sysproxy/darwin.js +0 -287
  96. package/dist/sysproxy/gnome.js +0 -181
  97. package/dist/sysproxy/legacy.js +0 -58
  98. package/dist/tun-guidance.js +0 -11
  99. package/dist/ui/assets/CodeEditorModal-6m0TJWyF.css +0 -1
  100. package/dist/ui/assets/CodeEditorModal-CFEnWsyh.js +0 -14
  101. package/dist/ui/assets/ProfileEditorDialog-BydoZthX.js +0 -1
  102. package/dist/ui/assets/ProfilesView-Btc1DOxE.js +0 -2
  103. package/dist/ui/assets/ProfilesView-ByqdFNHN.css +0 -1
  104. package/dist/ui/assets/SettingsFileDialog-CNFEAVs4.js +0 -1
  105. package/dist/ui/assets/SettingsView-BlDhZkXQ.js +0 -2
  106. package/dist/ui/assets/SettingsView-CngS3vBM.css +0 -1
  107. package/dist/ui/assets/index-B61V60w_.js +0 -19
  108. package/dist/ui/assets/index-bkyxJG8J.css +0 -1
@@ -1,287 +0,0 @@
1
- import { compareStrings, errorMessage, formatHostPort, normalizeEnableOptions, parseProxyString, parseServiceName, runCmd, } from "./common.js";
2
- import { darwinSnapshot } from "./snapshot.js";
3
- import { SYSTEM_PROXY_SNAPSHOT_VERSION } from "./types.js";
4
- export function parseDarwinServices(output) {
5
- return output
6
- .split(/\r?\n/)
7
- .map((line) => line.trim())
8
- .filter((line) => line.length > 0 && !line.startsWith("*") && !line.startsWith("An asterisk"));
9
- }
10
- function getDarwinOutputValue(output, label) {
11
- const prefix = `${label}:`;
12
- const lowerCasePrefix = prefix.toLowerCase();
13
- for (const line of output.split(/\r\n?|\n/)) {
14
- if (line.slice(0, prefix.length).toLowerCase() === lowerCasePrefix) {
15
- return line.slice(prefix.length).replace(/^[^\S\r\n]+|[^\S\r\n]+$/g, "");
16
- }
17
- }
18
- return undefined;
19
- }
20
- function parseDarwinProxyOutput(output) {
21
- const enabledText = getDarwinOutputValue(output, "Enabled")?.toLowerCase();
22
- const server = getDarwinOutputValue(output, "Server");
23
- const portText = getDarwinOutputValue(output, "Port");
24
- const authenticatedText = getDarwinOutputValue(output, "Authenticated Proxy Enabled")?.toLowerCase();
25
- let enabled;
26
- if (enabledText === "yes")
27
- enabled = true;
28
- if (enabledText === "no")
29
- enabled = false;
30
- let port;
31
- if (portText !== undefined && /^\d+$/.test(portText)) {
32
- const parsed = Number.parseInt(portText, 10);
33
- if (parsed >= 0 && parsed <= 65_535)
34
- port = parsed;
35
- }
36
- let authenticated;
37
- if (authenticatedText === "yes" || authenticatedText === "on" || authenticatedText === "1") {
38
- authenticated = true;
39
- }
40
- if (authenticatedText === "no" || authenticatedText === "off" || authenticatedText === "0") {
41
- authenticated = false;
42
- }
43
- return {
44
- ...(enabled === undefined ? {} : { enabled }),
45
- ...(server === undefined ? {} : { server }),
46
- ...(port === undefined ? {} : { port }),
47
- ...(authenticated === undefined ? {} : { authenticated }),
48
- };
49
- }
50
- export function parseDarwinProxySetting(output) {
51
- const parsed = parseDarwinProxyOutput(output);
52
- if (parsed.enabled === undefined) {
53
- throw new Error("Invalid macOS networksetup output: missing Enabled state");
54
- }
55
- if (parsed.server === undefined) {
56
- throw new Error("Invalid macOS networksetup output: missing Server value");
57
- }
58
- if (parsed.port === undefined) {
59
- throw new Error("Invalid macOS networksetup output: missing or invalid Port value");
60
- }
61
- if (parsed.authenticated === undefined) {
62
- throw new Error("Invalid macOS networksetup output: missing authenticated proxy state");
63
- }
64
- return {
65
- enabled: parsed.enabled,
66
- server: parseProxyString(parsed.server, "macOS proxy server"),
67
- port: parsed.port,
68
- authenticated: parsed.authenticated,
69
- };
70
- }
71
- export function parseDarwinAutoProxySetting(output) {
72
- const enabledText = getDarwinOutputValue(output, "Enabled")?.toLowerCase();
73
- const urlText = getDarwinOutputValue(output, "URL");
74
- if (enabledText !== "yes" && enabledText !== "no") {
75
- throw new Error("Invalid macOS networksetup output: missing automatic proxy state");
76
- }
77
- if (urlText === undefined) {
78
- throw new Error("Invalid macOS networksetup output: missing automatic proxy URL");
79
- }
80
- return {
81
- enabled: enabledText === "yes",
82
- url: parseProxyString(urlText === "(null)" ? "" : urlText, "macOS automatic proxy URL"),
83
- };
84
- }
85
- async function listDarwinServices(run) {
86
- const services = parseDarwinServices(await run("networksetup", ["-listallnetworkservices"]));
87
- const canonical = services.map((service, index) => parseServiceName(service, `network service ${index}`));
88
- canonical.sort(compareStrings);
89
- for (let index = 1; index < canonical.length; index++) {
90
- if (canonical[index - 1] === canonical[index]) {
91
- throw new Error("Invalid macOS networksetup output: duplicate network service name");
92
- }
93
- }
94
- return canonical;
95
- }
96
- const DARWIN_PROXY_COMMANDS = [
97
- {
98
- kind: "web",
99
- set: "-setwebproxy",
100
- setState: "-setwebproxystate",
101
- get: "-getwebproxy",
102
- },
103
- {
104
- kind: "secureWeb",
105
- set: "-setsecurewebproxy",
106
- setState: "-setsecurewebproxystate",
107
- get: "-getsecurewebproxy",
108
- },
109
- {
110
- kind: "socks",
111
- set: "-setsocksfirewallproxy",
112
- setState: "-setsocksfirewallproxystate",
113
- get: "-getsocksfirewallproxy",
114
- },
115
- ];
116
- export async function captureDarwinSnapshot(run = runCmd) {
117
- const services = [];
118
- for (const service of await listDarwinServices(run)) {
119
- const settings = new Map();
120
- for (const command of DARWIN_PROXY_COMMANDS) {
121
- settings.set(command.kind, parseDarwinProxySetting(await run("networksetup", [command.get, service])));
122
- }
123
- const web = settings.get("web");
124
- const secureWeb = settings.get("secureWeb");
125
- const socks = settings.get("socks");
126
- if (!web || !secureWeb || !socks) {
127
- throw new Error("Failed to capture all macOS proxy protocols");
128
- }
129
- const auto = parseDarwinAutoProxySetting(await run("networksetup", ["-getautoproxyurl", service]));
130
- services.push({ service, web, secureWeb, socks, auto });
131
- }
132
- return {
133
- version: SYSTEM_PROXY_SNAPSHOT_VERSION,
134
- platform: "darwin",
135
- services,
136
- };
137
- }
138
- function assertNoAuthenticatedDarwinProxy(snapshot) {
139
- for (const service of snapshot.services) {
140
- for (const command of DARWIN_PROXY_COMMANDS) {
141
- if (service[command.kind].authenticated) {
142
- throw new Error(`Cannot safely take over macOS proxy for ${JSON.stringify(service.service)}: ${command.kind} uses an authenticated proxy whose credentials cannot be restored`);
143
- }
144
- }
145
- }
146
- }
147
- export async function applyDarwinSnapshot(value, run = runCmd) {
148
- const snapshot = darwinSnapshot(value);
149
- assertNoAuthenticatedDarwinProxy(snapshot);
150
- const activeServices = await listDarwinServices(run);
151
- const snapshotServices = snapshot.services.map((service) => service.service);
152
- if (activeServices.length !== snapshotServices.length ||
153
- activeServices.some((service, index) => service !== snapshotServices[index])) {
154
- throw new Error("macOS network service collection changed; refusing to apply a stale proxy snapshot");
155
- }
156
- const failures = [];
157
- for (const service of snapshot.services) {
158
- for (const command of DARWIN_PROXY_COMMANDS) {
159
- const setting = service[command.kind];
160
- try {
161
- await run("networksetup", [
162
- command.set,
163
- service.service,
164
- setting.server,
165
- String(setting.port),
166
- ]);
167
- }
168
- catch (err) {
169
- failures.push(`${JSON.stringify(service.service)} ${command.kind} server/port: ${errorMessage(err)}`);
170
- }
171
- }
172
- if (service.auto.url) {
173
- try {
174
- await run("networksetup", ["-setautoproxyurl", service.service, service.auto.url]);
175
- }
176
- catch (err) {
177
- failures.push(`${JSON.stringify(service.service)} automatic proxy URL: ${errorMessage(err)}`);
178
- }
179
- }
180
- const stateOperations = [
181
- ...DARWIN_PROXY_COMMANDS.map((command) => ({
182
- label: command.kind,
183
- command: command.setState,
184
- enabled: service[command.kind].enabled,
185
- })),
186
- {
187
- label: "automatic proxy",
188
- command: "-setautoproxystate",
189
- enabled: service.auto.enabled,
190
- },
191
- ];
192
- for (const operation of [
193
- ...stateOperations.filter((item) => !item.enabled),
194
- ...stateOperations.filter((item) => item.enabled),
195
- ]) {
196
- try {
197
- await run("networksetup", [
198
- operation.command,
199
- service.service,
200
- operation.enabled ? "on" : "off",
201
- ]);
202
- }
203
- catch (err) {
204
- failures.push(`${JSON.stringify(service.service)} ${operation.label} state: ${errorMessage(err)}`);
205
- }
206
- }
207
- }
208
- if (failures.length > 0) {
209
- throw new Error(`Failed to apply macOS system proxy settings: ${failures.join("; ")}`);
210
- }
211
- }
212
- export function createDarwinTarget(original, opts) {
213
- const snapshot = darwinSnapshot(original);
214
- assertNoAuthenticatedDarwinProxy(snapshot);
215
- if (snapshot.services.length === 0) {
216
- throw new Error("Cannot enable macOS system proxy: no active network services found");
217
- }
218
- const normalized = normalizeEnableOptions(opts);
219
- const targetSetting = () => ({
220
- enabled: true,
221
- server: normalized.host,
222
- port: normalized.port,
223
- authenticated: false,
224
- });
225
- return {
226
- version: SYSTEM_PROXY_SNAPSHOT_VERSION,
227
- platform: "darwin",
228
- services: snapshot.services.map((service) => ({
229
- service: service.service,
230
- web: targetSetting(),
231
- secureWeb: targetSetting(),
232
- socks: targetSetting(),
233
- auto: { ...service.auto, enabled: false },
234
- })),
235
- };
236
- }
237
- export function darwinState(value) {
238
- const snapshot = darwinSnapshot(value);
239
- if (snapshot.services.length === 0) {
240
- return { supported: true, enabled: false, details: "no active network services found" };
241
- }
242
- const enabledSettings = [];
243
- const enabledAutoUrls = [];
244
- for (const service of snapshot.services) {
245
- for (const command of DARWIN_PROXY_COMMANDS) {
246
- const setting = service[command.kind];
247
- if (setting.enabled)
248
- enabledSettings.push(setting);
249
- }
250
- if (service.auto.enabled)
251
- enabledAutoUrls.push(service.auto.url);
252
- }
253
- if (enabledSettings.length === 0 && enabledAutoUrls.length === 0) {
254
- return { supported: true, enabled: false };
255
- }
256
- if (enabledSettings.length === 0) {
257
- const urls = new Set(enabledAutoUrls.filter(Boolean));
258
- return {
259
- supported: true,
260
- enabled: true,
261
- ...(urls.size === 1 ? { server: urls.values().next().value } : {}),
262
- details: "automatic proxy configuration is enabled",
263
- };
264
- }
265
- const endpoints = new Set();
266
- let hasIncompleteEndpoint = false;
267
- for (const setting of enabledSettings) {
268
- if (!setting.server || setting.port === 0) {
269
- hasIncompleteEndpoint = true;
270
- continue;
271
- }
272
- endpoints.add(formatHostPort(setting.server, setting.port));
273
- }
274
- if (endpoints.size === 1 && !hasIncompleteEndpoint && enabledAutoUrls.length === 0) {
275
- const server = endpoints.values().next().value;
276
- return typeof server === "string"
277
- ? { supported: true, enabled: true, server }
278
- : { supported: true, enabled: true };
279
- }
280
- return {
281
- supported: true,
282
- enabled: true,
283
- details: enabledAutoUrls.length > 0
284
- ? "manual and automatic proxy settings are both active"
285
- : "multiple or incomplete active proxy settings",
286
- };
287
- }
@@ -1,181 +0,0 @@
1
- import { formatHostPort, isSystemProxySupported, normalizeEnableOptions, parseProxyString, runCmd, } from "./common.js";
2
- import { linuxSnapshot } from "./snapshot.js";
3
- import { SYSTEM_PROXY_SNAPSHOT_VERSION } from "./types.js";
4
- function ensureGSettingsAvailable() {
5
- if (!isSystemProxySupported("linux")) {
6
- throw new Error("System proxy cannot be configured automatically: gsettings is not available on this system.");
7
- }
8
- }
9
- function decodeGSettingsString(content) {
10
- let decoded = "";
11
- for (let index = 0; index < content.length; index++) {
12
- const char = content[index];
13
- if (char !== "\\") {
14
- decoded += char;
15
- continue;
16
- }
17
- const escaped = content[index + 1];
18
- if (escaped === undefined)
19
- throw new Error("Invalid gsettings string: trailing escape");
20
- index++;
21
- switch (escaped) {
22
- case "\\":
23
- decoded += "\\";
24
- break;
25
- case "'":
26
- decoded += "'";
27
- break;
28
- case "n":
29
- decoded += "\n";
30
- break;
31
- case "r":
32
- decoded += "\r";
33
- break;
34
- case "t":
35
- decoded += "\t";
36
- break;
37
- case "b":
38
- decoded += "\b";
39
- break;
40
- case "f":
41
- decoded += "\f";
42
- break;
43
- default:
44
- throw new Error(`Invalid gsettings string: unsupported escape \\${escaped}`);
45
- }
46
- }
47
- return decoded;
48
- }
49
- export function parseGSettingsString(output) {
50
- const value = output.trim();
51
- if (value.length < 2 || !value.startsWith("'") || !value.endsWith("'")) {
52
- throw new Error("Invalid gsettings string: expected a single-quoted value");
53
- }
54
- return decodeGSettingsString(value.slice(1, -1));
55
- }
56
- function formatGSettingsString(value) {
57
- return `'${value.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
58
- }
59
- export function parseGSettingsPort(output, label) {
60
- const value = output.trim();
61
- const match = value.match(/^(?:uint16\s+)?(\d+)$/);
62
- if (!match?.[1]) {
63
- throw new Error(`Invalid gsettings ${label}: expected an integer`);
64
- }
65
- const port = Number.parseInt(match[1], 10);
66
- if (port < 0 || port > 65_535) {
67
- throw new Error(`Invalid gsettings ${label}: expected an integer from 0 to 65535`);
68
- }
69
- return port;
70
- }
71
- function parseGSettingsBoolean(output, label) {
72
- const value = output.trim();
73
- if (value === "true")
74
- return true;
75
- if (value === "false")
76
- return false;
77
- throw new Error(`Invalid gsettings ${label}: expected true or false`);
78
- }
79
- async function getLinuxEndpoint(protocol, run) {
80
- const schema = `org.gnome.system.proxy.${protocol}`;
81
- return {
82
- host: parseProxyString(await runGSettingsGet(schema, "host", run), `${protocol} host`),
83
- port: parseGSettingsPort(await run("gsettings", ["get", schema, "port"]), `${protocol} port`),
84
- };
85
- }
86
- async function runGSettingsGet(schema, key, run) {
87
- return parseGSettingsString(await run("gsettings", ["get", schema, key]));
88
- }
89
- export async function captureLinuxSnapshot(run = runCmd, ensureAvailable = ensureGSettingsAvailable) {
90
- ensureAvailable();
91
- const mode = await runGSettingsGet("org.gnome.system.proxy", "mode", run);
92
- if (mode !== "none" && mode !== "manual" && mode !== "auto") {
93
- throw new Error("Invalid gsettings mode: expected none, manual, or auto");
94
- }
95
- const autoConfigUrl = await runGSettingsGet("org.gnome.system.proxy", "autoconfig-url", run);
96
- const httpUseAuthentication = parseGSettingsBoolean(await run("gsettings", ["get", "org.gnome.system.proxy.http", "use-authentication"]), "HTTP authentication state");
97
- const http = await getLinuxEndpoint("http", run);
98
- const https = await getLinuxEndpoint("https", run);
99
- const socks = await getLinuxEndpoint("socks", run);
100
- return {
101
- version: SYSTEM_PROXY_SNAPSHOT_VERSION,
102
- platform: "linux",
103
- mode,
104
- autoConfigUrl,
105
- httpUseAuthentication,
106
- http,
107
- https,
108
- socks,
109
- };
110
- }
111
- export async function applyLinuxSnapshot(value, run = runCmd, ensureAvailable = ensureGSettingsAvailable) {
112
- const snapshot = linuxSnapshot(value);
113
- ensureAvailable();
114
- const endpoints = [
115
- { schema: "org.gnome.system.proxy.http", value: snapshot.http },
116
- { schema: "org.gnome.system.proxy.https", value: snapshot.https },
117
- { schema: "org.gnome.system.proxy.socks", value: snapshot.socks },
118
- ];
119
- await run("gsettings", [
120
- "set",
121
- "org.gnome.system.proxy",
122
- "autoconfig-url",
123
- formatGSettingsString(snapshot.autoConfigUrl),
124
- ]);
125
- await run("gsettings", [
126
- "set",
127
- "org.gnome.system.proxy.http",
128
- "use-authentication",
129
- snapshot.httpUseAuthentication ? "true" : "false",
130
- ]);
131
- for (const endpoint of endpoints) {
132
- await run("gsettings", [
133
- "set",
134
- endpoint.schema,
135
- "host",
136
- formatGSettingsString(endpoint.value.host),
137
- ]);
138
- await run("gsettings", ["set", endpoint.schema, "port", String(endpoint.value.port)]);
139
- }
140
- await run("gsettings", [
141
- "set",
142
- "org.gnome.system.proxy",
143
- "mode",
144
- formatGSettingsString(snapshot.mode),
145
- ]);
146
- }
147
- export function createLinuxTarget(original, opts) {
148
- const snapshot = linuxSnapshot(original);
149
- const normalized = normalizeEnableOptions(opts);
150
- const endpoint = () => ({ host: normalized.host, port: normalized.port });
151
- return {
152
- version: SYSTEM_PROXY_SNAPSHOT_VERSION,
153
- platform: "linux",
154
- mode: "manual",
155
- autoConfigUrl: snapshot.autoConfigUrl,
156
- httpUseAuthentication: false,
157
- http: endpoint(),
158
- https: endpoint(),
159
- socks: endpoint(),
160
- };
161
- }
162
- export function linuxState(value) {
163
- const snapshot = linuxSnapshot(value);
164
- if (snapshot.mode === "auto") {
165
- return {
166
- supported: true,
167
- enabled: true,
168
- ...(snapshot.autoConfigUrl ? { server: snapshot.autoConfigUrl } : {}),
169
- details: "automatic proxy configuration is enabled",
170
- };
171
- }
172
- const enabled = snapshot.mode === "manual";
173
- if (!enabled || !snapshot.http.host || snapshot.http.port === 0) {
174
- return { supported: true, enabled };
175
- }
176
- return {
177
- supported: true,
178
- enabled,
179
- server: formatHostPort(snapshot.http.host, snapshot.http.port),
180
- };
181
- }
@@ -1,58 +0,0 @@
1
- import { formatHostPort, normalizeEnableOptions } from "./common.js";
2
- import { createSystemProxyBackend } from "./factory.js";
3
- import { parseSystemProxySnapshot } from "./snapshot.js";
4
- export function createLegacyProxyCleanup(value, opts) {
5
- const snapshot = parseSystemProxySnapshot(value);
6
- const normalized = normalizeEnableOptions(opts);
7
- const target = formatHostPort(normalized.host, normalized.port);
8
- switch (snapshot.platform) {
9
- case "win32":
10
- return snapshot.proxyEnable === 1 && snapshot.proxyServer === target
11
- ? { ...snapshot, proxyEnable: 0 }
12
- : undefined;
13
- case "darwin": {
14
- let matched = false;
15
- let conflict = false;
16
- const clean = (setting) => {
17
- if (!setting.enabled)
18
- return setting;
19
- if (formatHostPort(setting.server, setting.port) !== target) {
20
- conflict = true;
21
- return setting;
22
- }
23
- matched = true;
24
- return { ...setting, enabled: false };
25
- };
26
- const services = snapshot.services.map((service) => ({
27
- ...service,
28
- web: clean(service.web),
29
- secureWeb: clean(service.secureWeb),
30
- socks: clean(service.socks),
31
- }));
32
- if (!matched || conflict)
33
- return undefined;
34
- return { ...snapshot, services };
35
- }
36
- case "linux":
37
- if (snapshot.mode !== "manual" ||
38
- [snapshot.http, snapshot.https, snapshot.socks].some((endpoint) => formatHostPort(endpoint.host, endpoint.port) !== target)) {
39
- return undefined;
40
- }
41
- return { ...snapshot, mode: "none" };
42
- }
43
- }
44
- export async function disableLegacySystemProxyIfOwned(opts) {
45
- const backend = createSystemProxyBackend();
46
- if (backend.supported === false)
47
- return false;
48
- const current = await backend.capture();
49
- const cleanup = createLegacyProxyCleanup(current, opts);
50
- if (!cleanup)
51
- return false;
52
- await backend.apply(cleanup);
53
- const verified = await backend.capture();
54
- if (!backend.equivalent(verified, cleanup)) {
55
- throw new Error("Legacy system proxy cleanup could not be verified");
56
- }
57
- return true;
58
- }
@@ -1,11 +0,0 @@
1
- function quotePosix(value) {
2
- return `'${value.replaceAll("'", "'\\''")}'`;
3
- }
4
- export function tunPrivilegeGuidance(context, options) {
5
- const platform = options.platform ?? process.platform;
6
- const prepare = context === "activation-rolled-back" ? 'Run "sash config set tun on" first. ' : "";
7
- if (platform === "win32") {
8
- return `${prepare}Open PowerShell as Administrator and run "sash restart". If SASH_HOME was explicitly customized, set the same value in that shell first. If Sash was already elevated, inspect the Core error log.`;
9
- }
10
- return `${prepare}Restart Sash with root privileges using the same data directory: sudo env SASH_HOME=${quotePosix(options.root)} "$(command -v sash)" restart. If Sash was already elevated, inspect the Core error log.`;
11
- }
@@ -1 +0,0 @@
1
- .editor-overlay[data-v-31142826]{position:fixed;inset:0;z-index:var(--z-dialog);display:flex;padding:26px;background:var(--bg-scrim)}.editor-dialog[data-v-31142826]{display:flex;width:100%;min-height:0;flex:1;flex-direction:column;overflow:hidden;background:var(--bg-elevated);border-radius:var(--radius-md);box-shadow:var(--shadow-pop)}.editor-dialog-constrained[data-v-31142826]{max-width:720px;max-height:100%;margin:auto;flex:0 1 auto}.editor-head[data-v-31142826]{display:flex;min-height:46px;align-items:center;gap:12px;padding:6px 10px 6px 16px;border-bottom:1px solid var(--border)}.editor-name[data-v-31142826]{min-width:0;overflow:hidden;color:var(--text-primary);font-size:16px;font-weight:600;text-overflow:ellipsis;white-space:nowrap}.editor-hint[data-v-31142826]{min-width:0;flex:1;overflow:hidden;color:var(--warning);font-size:14px;text-overflow:ellipsis;white-space:nowrap}.editor-actions[data-v-31142826]{display:flex;flex-shrink:0;gap:8px;margin-left:auto}.editor-error[data-v-31142826]{padding:18px 20px;color:var(--danger);font-size:16px}.editor-host[data-v-31142826]{position:relative;min-height:0;flex:1;overflow:hidden}.editor-host-constrained[data-v-31142826]{min-height:320px}.editor-loading[data-v-31142826]{position:absolute;top:12px;left:16px;color:var(--text-muted);font-size:16px}.editor-host[data-v-31142826] .cm-editor{height:100%;font-size:16px}.editor-host[data-v-31142826] .cm-editor .cm-scroller{font-family:var(--font-mono)}.editor-host[data-v-31142826] .cm-editor.cm-focused{outline:none}@media(max-width:640px){.editor-overlay[data-v-31142826]{padding:0}.editor-dialog[data-v-31142826]{border-radius:0}.editor-dialog-constrained[data-v-31142826]{max-width:none}.editor-hint[data-v-31142826]{display:none}}