Skip to content

Commit bb68cef

Browse files
authored
refactor(desktop): simplify TypeScript contracts and test mocks (#214)
1 parent fad3eea commit bb68cef

136 files changed

Lines changed: 1310 additions & 2760 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

desktop/src/main/appServerRetry.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import type { ConnectionMode } from './settings'
2-
3-
export interface RetryConnectionRequest {
4-
restartManaged?: boolean
5-
}
2+
import type { RetryConnectionRequest } from '../shared/connectionStatus'
3+
export type { RetryConnectionRequest } from '../shared/connectionStatus'
64

75
export interface AppServerRetryContext {
86
currentWorkspacePath: string

desktop/src/main/browserUseManager.ts

Lines changed: 7 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@ import {
1818
normalizeBrowserUseDomainList,
1919
resolveBrowserUseNavigationDecision
2020
} from './browserUsePolicy'
21+
import type {
22+
BrowserUseApprovalRequestPayload,
23+
BrowserUseApprovalResponseAction,
24+
BrowserUseApprovalResponsePayload,
25+
BrowserUseClosePayload,
26+
BrowserUseOpenPayload
27+
} from '../shared/viewer/types'
2128

2229
const require = createRequire(import.meta.url)
2330
const playwrightCoreRoot = dirname(require.resolve('playwright-core/package.json'))
@@ -242,35 +249,6 @@ export interface BrowserUseImageResult {
242249
dataBase64: string
243250
}
244251

245-
export interface BrowserUseOpenPayload {
246-
threadId: string
247-
tabId: string
248-
initialUrl: string
249-
title?: string
250-
focusMode: 'first-open' | 'none'
251-
}
252-
253-
export interface BrowserUseClosePayload {
254-
threadId: string
255-
tabId: string
256-
}
257-
258-
export type BrowserUseApprovalResponseAction = 'allowOnce' | 'allowDomain' | 'blockDomain' | 'deny'
259-
260-
export interface BrowserUseApprovalRequestPayload {
261-
requestId: string
262-
threadId: string
263-
tabId: string
264-
url: string
265-
domain: string
266-
sessionName?: string
267-
}
268-
269-
export interface BrowserUseApprovalResponsePayload {
270-
requestId: string
271-
action: BrowserUseApprovalResponseAction
272-
}
273-
274252
interface BrowserUseViewerHost {
275253
createAutomationTab(win: BrowserWindow, params: {
276254
tabId: string

desktop/src/main/channelModuleManager.ts

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,22 @@
11
import { promises as fs } from 'fs'
22
import * as path from 'path'
33
import type { DesktopAppServerClient } from './DesktopAppServerClient'
4-
import type { DiscoveredModule } from './moduleScanner'
5-
import { QrFileWatcher, type QrUpdatePayload } from './qrWatcher'
6-
7-
export type ProcessState = 'starting' | 'running' | 'stopping' | 'stopped' | 'crashed'
4+
import type {
5+
DiscoveredModule,
6+
ModuleProcessState,
7+
ModuleStatusMap,
8+
QrUpdatePayload
9+
} from '../shared/channelModules'
10+
export type { ModuleStatusEntry, ModuleStatusMap } from '../shared/channelModules'
11+
import { QrFileWatcher } from './qrWatcher'
812

913
interface ManagedModuleProcess {
1014
moduleId: string
1115
channelName: string
12-
state: ProcessState
16+
state: ModuleProcessState
1317
failureCode: string | null
1418
}
1519

16-
export interface ModuleStatusEntry {
17-
processState: ProcessState
18-
connected: boolean
19-
failureCode?: string
20-
}
21-
22-
export type ModuleStatusMap = Record<string, ModuleStatusEntry>
23-
2420
interface ChannelStatusWire {
2521
name: string
2622
enabled: boolean

desktop/src/main/chromeSetup.ts

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,13 @@ import { existsSync, promises as fsPromises, readFileSync } from 'fs'
44
import { tmpdir } from 'os'
55
import { join } from 'path'
66
import net from 'net'
7+
import type { ChromeSetupCheckStatus, ChromeSetupStatus } from '../shared/chromeSetup'
8+
export type { ChromeSetupCheckStatus, ChromeSetupStatus } from '../shared/chromeSetup'
79

810
export interface ChromeOpenRequest {
911
url?: string
1012
}
1113

12-
export interface ChromeSetupCheckStatus {
13-
ok: boolean
14-
code: string
15-
message: string
16-
action?: string
17-
safeDetails?: Record<string, string | number | boolean>
18-
}
19-
20-
export interface ChromeSetupStatus {
21-
extension: ChromeSetupCheckStatus
22-
nativeHost: ChromeSetupCheckStatus
23-
chromeRunning: ChromeSetupCheckStatus
24-
installedBrowsers: ChromeSetupCheckStatus
25-
backend: ChromeSetupCheckStatus
26-
bridge: ChromeSetupCheckStatus
27-
}
28-
2914
export function resolveBundledChromePluginRoot(): string {
3015
if (app.isPackaged) {
3116
return join(process.resourcesPath, 'plugins', 'dotcraft-bundled', 'plugins', 'chrome')

desktop/src/main/externalEditors.ts

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,8 @@ import { access, stat } from 'fs/promises'
22
import * as path from 'path'
33
import { execFile, spawn, type ChildProcess, type SpawnOptions } from 'child_process'
44
import { app, shell } from 'electron'
5-
6-
export type EditorId =
7-
| 'explorer'
8-
| 'vs'
9-
| 'cursor'
10-
| 'vscode'
11-
| 'rider'
12-
| 'webstorm'
13-
| 'idea'
14-
| 'github-desktop'
15-
| 'git-bash'
16-
| 'terminal'
17-
18-
export interface EditorInfo {
19-
id: EditorId
20-
labelKey: string
21-
iconKey: string
22-
iconDataUrl?: string
23-
}
5+
import type { EditorId, EditorInfo } from '../shared/externalEditors'
6+
export type { EditorId, EditorInfo } from '../shared/externalEditors'
247

258
interface EditorDescriptor extends EditorInfo {
269
command: string

desktop/src/main/index.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,12 @@ import {
5555
createServerRequestBridge,
5656
sanitizeHttpOrHttpsUrl,
5757
openExternalHttpUrl,
58-
type ConnectionErrorType,
59-
type ConnectionStatusPayload,
6058
type IpcHandlerCallbacks
6159
} from './ipcBridge'
60+
import type {
61+
ConnectionErrorType,
62+
ConnectionStatusPayload
63+
} from '../shared/connectionStatus'
6264
import {
6365
loadSettings,
6466
saveSettings,
@@ -105,11 +107,13 @@ import {
105107
shouldRouteWorkspaceThroughSetupBeforeAppServerStart,
106108
runWorkspaceSetup,
107109
listSetupModels,
108-
loginSetupChatGpt,
109-
type WorkspaceStatusPayload,
110-
type WorkspaceSetupRequest,
111-
type WorkspaceSetupModelListRequest
110+
loginSetupChatGpt
112111
} from './workspaceSetup'
112+
import type {
113+
WorkspaceSetupModelListRequest,
114+
WorkspaceSetupRequest,
115+
WorkspaceStatusPayload
116+
} from '../shared/workspaceSetup'
113117
import { encodeInitialWorkspaceStatusArg } from '../shared/initialWorkspaceStatus'
114118
import { getEnabledEmbeddedModuleChannelNames } from '../shared/channelModulePersistence'
115119
import { applyWindowBackdropTheme, resolveInitialTheme, resolveWindowBackdropOptions } from './windowTheme'

desktop/src/main/ipcBridge.ts

Lines changed: 8 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ import {
6060
} from './desktopExtensionGrants'
6161
import { partitionForWorkspace, viewerBrowserManager } from './viewerBrowser'
6262
import { viewerTerminalManager } from './viewerTerminal'
63-
import { browserUseManager, type BrowserUseApprovalResponsePayload } from './browserUseManager'
63+
import { browserUseManager } from './browserUseManager'
64+
import type { BrowserUseApprovalResponsePayload } from '../shared/viewer/types'
6465
import {
6566
checkChromeSetup,
6667
installChromeNativeHost,
@@ -79,11 +80,11 @@ import {
7980
import type { QrUpdatePayload } from './qrWatcher'
8081
import type {
8182
WorkspaceSetupRequest,
82-
WorkspaceSetupResult,
8383
WorkspaceStatusPayload,
8484
WorkspaceSetupModelListRequest,
8585
WorkspaceSetupModelListResult
86-
} from './workspaceSetup'
86+
} from '../shared/workspaceSetup'
87+
import type { WorkspaceSetupResult } from './workspaceSetup'
8788
import { normalizeRemoteHosts, type RemoteHost, type RemoteStack } from '../shared/remoteServers'
8889
import { translate, normalizeLocale, DEFAULT_LOCALE, type AppLocale } from '../shared/locales'
8990
import { parseJsonObjectConfig } from '../shared/jsonConfig'
@@ -112,46 +113,22 @@ import { sendDesktopAppServerRequest } from './desktopRuntimeThreadTools'
112113
import { resolveBundledBuiltInPluginRoot } from './ripgrepRuntime'
113114
import type { WorkspaceProjectsPayload } from '../shared/workspaceProjects'
114115
import type { AppServerRequestMethod } from '../shared/appServerBoundary'
116+
import type {
117+
ConnectionStatusPayload,
118+
RetryConnectionRequest
119+
} from '../shared/connectionStatus'
115120

116121
interface WindowVisibilityState {
117122
minimized: boolean
118123
visible: boolean
119124
focused: boolean
120125
}
121126

122-
export type ConnectionStatus = 'connecting' | 'connected' | 'disconnected' | 'error'
123-
124-
export type ConnectionErrorType = 'binary-not-found' | 'handshake-timeout' | 'crash' | 'remote-config-invalid'
125-
126-
export interface ConnectionStatusPayload {
127-
status: ConnectionStatus
128-
serverInfo?: {
129-
name: string
130-
version: string
131-
protocolVersion?: string
132-
}
133-
capabilities?: Record<string, unknown>
134-
/** DashBoard URL when the server hosts it (initialize). */
135-
dashboardUrl?: string
136-
errorMessage?: string
137-
errorType?: ConnectionErrorType
138-
binarySource?: BinarySource
139-
}
140-
141-
export interface RetryConnectionRequest {
142-
restartManaged?: boolean
143-
}
144-
145127
export interface ResolvedBinaryRequest {
146128
binarySource?: BinarySource
147129
binaryPath?: string
148130
}
149131

150-
export interface ResolvedBinaryPayload {
151-
source: BinarySource
152-
path: string | null
153-
}
154-
155132
interface ModulesRescanSummaryPayload {
156133
addedModuleIds: string[]
157134
removedModuleIds: string[]

desktop/src/main/moduleScanner.ts

Lines changed: 14 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -4,68 +4,20 @@ import type { Dirent } from 'fs'
44
import * as path from 'path'
55
import type { AppSettings } from './settings'
66
import { SUPPORTED_LOCALE_VALUES, type LocalizedTextMap } from '../shared/locales'
7-
8-
export interface ConfigDescriptorWire {
9-
key: string
10-
displayLabel: string
11-
description: string
12-
localizedDisplayLabel?: LocalizedTextMap
13-
localizedDescription?: LocalizedTextMap
14-
required: boolean
15-
dataKind: string
16-
masked: boolean
17-
interactiveSetupOnly: boolean
18-
group?: string
19-
advanced?: boolean
20-
defaultValue?: unknown
21-
options?: ConfigFieldOptionWire[]
22-
allowCustomValue?: boolean
23-
enumValues?: string[]
24-
}
25-
26-
export interface ConfigFieldOptionWire {
27-
value: string
28-
displayLabel: string
29-
localizedDisplayLabel?: LocalizedTextMap
30-
description?: string
31-
localizedDescription?: LocalizedTextMap
32-
preview?: string
33-
}
34-
35-
export interface ConfigGroupDescriptorWire {
36-
id: string
37-
displayLabel: string
38-
localizedDisplayLabel?: LocalizedTextMap
39-
description?: string
40-
localizedDescription?: LocalizedTextMap
41-
}
42-
43-
export interface ModuleInterfaceWire {
44-
shortDescription?: string
45-
localizedShortDescription?: LocalizedTextMap
46-
longDescription?: string
47-
localizedLongDescription?: LocalizedTextMap
48-
previewPrompt?: string
49-
localizedPreviewPrompt?: LocalizedTextMap
50-
}
51-
52-
export interface DiscoveredModule {
53-
moduleId: string
54-
channelName: string
55-
displayName: string
56-
localizedDisplayName?: LocalizedTextMap
57-
interface?: ModuleInterfaceWire
58-
packageName: string
59-
configFileName: string
60-
supportedTransports: string[]
61-
requiresInteractiveSetup: boolean
62-
capabilitySummary?: Record<string, unknown>
63-
variant: string
64-
source: 'bundled' | 'user'
65-
absolutePath: string
66-
configGroups?: ConfigGroupDescriptorWire[]
67-
configDescriptors: ConfigDescriptorWire[]
68-
}
7+
import type {
8+
ConfigDescriptorWire,
9+
ConfigFieldOptionWire,
10+
ConfigGroupDescriptorWire,
11+
DiscoveredModule,
12+
ModuleInterfaceWire
13+
} from '../shared/channelModules'
14+
export type {
15+
ConfigDescriptorWire,
16+
ConfigFieldOptionWire,
17+
ConfigGroupDescriptorWire,
18+
DiscoveredModule,
19+
ModuleInterfaceWire
20+
} from '../shared/channelModules'
6921

7022
export interface ChannelModuleGroup {
7123
channelName: string

desktop/src/main/qrWatcher.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,14 @@
11
import { promises as fs, watch, type FSWatcher } from 'fs'
22
import * as path from 'path'
3+
import type { QrUpdatePayload } from '../shared/channelModules'
4+
export type { QrUpdatePayload } from '../shared/channelModules'
35

46
const DIR_POLL_INTERVAL_MS = 500
57
const DIR_POLL_MAX_ATTEMPTS = 60
68
const QR_READ_DEBOUNCE_MS = 200
79

810
export type QrWatchPhase = 'idle' | 'waitingForDir' | 'watching' | 'loginComplete'
911

10-
export interface QrUpdatePayload {
11-
moduleId: string
12-
qrDataUrl: string | null
13-
timestamp: number
14-
}
15-
1612
interface QrWatchState {
1713
moduleId: string
1814
phase: QrWatchPhase

0 commit comments

Comments
 (0)