feat: desktop v2 everything WSL (#23407)
This commit is contained in:
@@ -3,6 +3,7 @@ import type { AsyncStorage, SyncStorage } from "@solid-primitives/storage"
|
||||
import type { Accessor } from "solid-js"
|
||||
import type { DesktopMenuAction } from "../desktop-menu"
|
||||
import { ServerConnection } from "./server"
|
||||
import type { WslServersPlatform } from "../wsl/types"
|
||||
|
||||
type PickerPaths = string | string[] | null
|
||||
type OpenDirectoryPickerOptions = { title?: string; multiple?: boolean }
|
||||
@@ -75,11 +76,8 @@ export type Platform = {
|
||||
/** Set the default server URL to use on app startup (platform-specific) */
|
||||
setDefaultServer?(url: ServerConnection.Key | null): Promise<void> | void
|
||||
|
||||
/** Get the configured WSL integration (desktop only) */
|
||||
getWslEnabled?(): Promise<boolean>
|
||||
|
||||
/** Set the configured WSL integration (desktop only) */
|
||||
setWslEnabled?(config: boolean): Promise<void> | void
|
||||
/** Manage WSL sidecar servers (Electron on Windows only) */
|
||||
wslServers?: WslServersPlatform
|
||||
|
||||
/** Get the preferred display backend (desktop only) */
|
||||
getDisplayBackend?(): Promise<DisplayBackend | null> | DisplayBackend | null
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
import { describe, expect, test } from "bun:test"
|
||||
import { createRoot, createSignal } from "solid-js"
|
||||
import { createStore } from "solid-js/store"
|
||||
import { createServerProjects, migrateCanonicalLocalServerState, resolveServerList, ServerConnection } from "./server"
|
||||
import {
|
||||
createServerProjects,
|
||||
migrateCanonicalLocalServerState,
|
||||
nextServerAfterRemoval,
|
||||
resolveServerList,
|
||||
ServerConnection,
|
||||
} from "./server"
|
||||
import { ServerScope } from "@/utils/server-scope"
|
||||
|
||||
describe("resolveServerList", () => {
|
||||
@@ -55,6 +61,40 @@ describe("resolveServerList", () => {
|
||||
})
|
||||
})
|
||||
|
||||
test("treats WSL sidecars as remote server connections", () => {
|
||||
expect(
|
||||
ServerConnection.local({
|
||||
type: "sidecar",
|
||||
variant: "wsl",
|
||||
distro: "Debian",
|
||||
http: { url: "http://127.0.0.1:4097" },
|
||||
}),
|
||||
).toBe(false)
|
||||
expect(ServerConnection.local({ type: "sidecar", variant: "base", http: { url: "http://127.0.0.1:4096" } })).toBe(
|
||||
true,
|
||||
)
|
||||
expect(ServerConnection.local({ type: "http", http: { url: "http://localhost:4096" } })).toBe(true)
|
||||
expect(ServerConnection.local({ type: "http", http: { url: "https://server.example.test" } })).toBe(false)
|
||||
})
|
||||
|
||||
test("active server removal falls back across built-in and persisted servers", () => {
|
||||
const local = { type: "sidecar", variant: "base", http: { url: "http://127.0.0.1:4096" } } as const
|
||||
const debian = {
|
||||
type: "sidecar",
|
||||
variant: "wsl",
|
||||
distro: "Debian",
|
||||
http: { url: "http://127.0.0.1:4097" },
|
||||
} as const
|
||||
|
||||
expect(
|
||||
nextServerAfterRemoval(
|
||||
[local, debian],
|
||||
ServerConnection.Key.make("wsl:Debian"),
|
||||
ServerConnection.Key.make("sidecar"),
|
||||
),
|
||||
).toBe(ServerConnection.Key.make("sidecar"))
|
||||
})
|
||||
|
||||
describe("createServerProjects", () => {
|
||||
test("keeps active and explicit server buckets in one reactive store", () => {
|
||||
createRoot((dispose) => {
|
||||
|
||||
@@ -145,7 +145,7 @@ export function resolveServerList(input: {
|
||||
}
|
||||
|
||||
export namespace ServerConnection {
|
||||
type Base = { displayName?: string }
|
||||
type Base = { displayName?: string; label?: string }
|
||||
|
||||
export type HttpBase = {
|
||||
url: string
|
||||
@@ -204,6 +204,18 @@ export namespace ServerConnection {
|
||||
export const Key = { make: (v: string) => v as Key }
|
||||
|
||||
export const builtin = (conn: Any) => conn.type === "sidecar" && conn.variant === "base"
|
||||
export const local = (conn?: Any) =>
|
||||
!!conn && (builtin(conn) || (conn.type === "http" && isLocalHost(conn.http.url) === "local"))
|
||||
}
|
||||
|
||||
export function nextServerAfterRemoval(
|
||||
servers: ServerConnection.Any[],
|
||||
removed: ServerConnection.Key,
|
||||
fallback: ServerConnection.Key,
|
||||
) {
|
||||
const remaining = servers.filter((server) => ServerConnection.key(server) !== removed)
|
||||
const next = remaining.find((server) => ServerConnection.key(server) === fallback) ?? remaining[0]
|
||||
return next ? ServerConnection.key(next) : fallback
|
||||
}
|
||||
|
||||
export const { use: useServer, provider: ServerProvider } = createSimpleContext({
|
||||
@@ -257,13 +269,11 @@ export const { use: useServer, provider: ServerProvider } = createSimpleContext(
|
||||
}
|
||||
|
||||
function remove(key: ServerConnection.Key) {
|
||||
const next = nextServerAfterRemoval(allServers(), key, props.defaultServer)
|
||||
const list = store.list.filter((x) => url(x) !== key)
|
||||
batch(() => {
|
||||
setStore("list", list)
|
||||
if (state.active === key) {
|
||||
const next = list[0]
|
||||
setState("active", next ? ServerConnection.Key.make(url(next)) : props.defaultServer)
|
||||
}
|
||||
if (state.active === key) setState("active", next)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -282,10 +292,7 @@ export const { use: useServer, provider: ServerProvider } = createSimpleContext(
|
||||
const current: Accessor<ServerConnection.Any | undefined> = createMemo(
|
||||
() => allServers().find((s) => ServerConnection.key(s) === state.active) ?? allServers()[0],
|
||||
)
|
||||
const isLocal = createMemo(() => {
|
||||
const c = current()
|
||||
return (c?.type === "sidecar" && c.variant === "base") || (c?.type === "http" && isLocalHost(c.http.url))
|
||||
})
|
||||
const isLocal = createMemo(() => ServerConnection.local(current()))
|
||||
|
||||
return {
|
||||
ready: isReady,
|
||||
|
||||
Reference in New Issue
Block a user