mirror of
https://github.com/stablyai/orca.git
synced 2026-10-30 16:47:34 +00:00
refactor(orcad): move the Node host adapters out of orcad-entry.ts (#28530)
Fixes main's lint: #28464 left orcad-entry.ts at 301 lines (max 300). No behaviour change.
This commit is contained in:
@@ -11,16 +11,11 @@
|
||||
* Chromium proves available at startup.
|
||||
*/
|
||||
import process from 'node:process'
|
||||
import { describeOrcadSecretProtectionGap } from './orcad-secret-protection-gap'
|
||||
import {
|
||||
getAppEnvironment,
|
||||
setAppEnvironment,
|
||||
type AppEnvironment
|
||||
} from '../../shared/app-environment'
|
||||
import { setSecretStore, type SecretStore } from '../../shared/secret-store'
|
||||
import { getAppEnvironment } from '../../shared/app-environment'
|
||||
import type { ServeReadiness } from '../server/serve-readiness'
|
||||
import { resolveOrcadInstallRoot, resolveOrcadPath, resolveUserDataPath } from './orcad-app-paths'
|
||||
import { getOrcadCliLauncherPath, prepareOrcadCliLauncher } from './orcad-cli-launcher'
|
||||
import { resolveOrcadInstallRoot, resolveUserDataPath } from './orcad-app-paths'
|
||||
import { prepareOrcadCliLauncher } from './orcad-cli-launcher'
|
||||
import { installOrcadHostAdapters, runOrcadQuitHandlers } from './orcad-host-adapters'
|
||||
import { describeOrcadBindExposure, resolveOrcadBindHost } from './orcad-bind-address'
|
||||
import {
|
||||
flushOrcadProfileStoreForShutdown,
|
||||
@@ -43,68 +38,8 @@ import { adoptWslHostLoginEnvironment } from './orcad-wsl-host-login-environment
|
||||
|
||||
export { parseArgs }
|
||||
|
||||
let runOrcadQuitHandlers = (): void => {}
|
||||
let closeOrcadObservability = (): void => {}
|
||||
|
||||
function createNodeAppEnvironment(): AppEnvironment {
|
||||
const quitHandlers: (() => void)[] = []
|
||||
// The main signal handler awaits runtime and browser teardown before process.exit.
|
||||
// Keep will-quit callbacks synchronous, but never let them pre-empt that async barrier.
|
||||
runOrcadQuitHandlers = (): void => {
|
||||
const errors: unknown[] = []
|
||||
for (const handler of quitHandlers.splice(0)) {
|
||||
try {
|
||||
handler()
|
||||
} catch (error) {
|
||||
errors.push(error)
|
||||
}
|
||||
}
|
||||
// Why throw: a quit handler that failed may leave a writer running, which keeps the lock.
|
||||
if (errors.length > 0) {
|
||||
throw new AggregateError(errors, 'orcad_quit_handlers_failed')
|
||||
}
|
||||
}
|
||||
return {
|
||||
getPath: resolveOrcadPath,
|
||||
getAppPath: () => resolveOrcadInstallRoot(),
|
||||
getVersion: () => process.env.ORCA_VERSION ?? '0.0.0-orcad',
|
||||
// Why still true: consumers read this as "production build, not a dev checkout" —
|
||||
// it gates HTTPS-only skill downloads, the real CLI command name, and shell-PATH
|
||||
// hydration. Answering false to satisfy a path resolver would relax a security
|
||||
// posture. Layout questions must ask whether the app root is an asar archive
|
||||
// instead (see parcel-watcher-entry-path.ts).
|
||||
isPackaged: () => true,
|
||||
getCliLauncherPath: getOrcadCliLauncherPath,
|
||||
onWillQuit: (handler) => quitHandlers.push(handler),
|
||||
exit: (code = 0) => process.exit(code),
|
||||
// Why []: there are no Chromium processes on this host to measure.
|
||||
getAppMetrics: () => []
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Why not silently plaintext: `isEncryptionAvailable() === false` already makes every
|
||||
* caller fall back to unsealed storage, which is a security posture, not a detail.
|
||||
* `describeProtectionGap()` gives the reason a client can surface.
|
||||
*/
|
||||
function createNodeSecretStore(): SecretStore {
|
||||
return {
|
||||
isEncryptionAvailable: () => false,
|
||||
encryptString: () => {
|
||||
throw new Error('orcad_secret_sealing_unavailable')
|
||||
},
|
||||
decryptString: () => {
|
||||
throw new Error('orcad_secret_sealing_unavailable')
|
||||
},
|
||||
describeProtectionGap: () => describeOrcadSecretProtectionGap(process.platform)
|
||||
}
|
||||
}
|
||||
|
||||
export function installOrcadHostAdapters(): void {
|
||||
setAppEnvironment(createNodeAppEnvironment())
|
||||
setSecretStore(createNodeSecretStore())
|
||||
}
|
||||
|
||||
export type OrcadOptions = {
|
||||
port?: number
|
||||
json?: boolean
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
resolveForeignSqliteReaderEntryPath
|
||||
} from '../foreign-sqlite-readers/foreign-sqlite-reader-entry-path'
|
||||
import { currentWorkerEntryLayout } from '../worker-thread-entry-path'
|
||||
import { installOrcadHostAdapters } from './orcad-entry'
|
||||
import { installOrcadHostAdapters } from './orcad-host-adapters'
|
||||
|
||||
/**
|
||||
* The composition, not the pieces: orcad's real host adapters against the real resolver
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/** The Node host's stand-ins for Electron's app environment and secret store. */
|
||||
import process from 'node:process'
|
||||
import { setAppEnvironment, type AppEnvironment } from '../../shared/app-environment'
|
||||
import { setSecretStore, type SecretStore } from '../../shared/secret-store'
|
||||
import { resolveOrcadInstallRoot, resolveOrcadPath } from './orcad-app-paths'
|
||||
import { getOrcadCliLauncherPath } from './orcad-cli-launcher'
|
||||
import { describeOrcadSecretProtectionGap } from './orcad-secret-protection-gap'
|
||||
|
||||
let quitRegisteredHandlers = (): void => {}
|
||||
|
||||
export function runOrcadQuitHandlers(): void {
|
||||
quitRegisteredHandlers()
|
||||
}
|
||||
|
||||
function createNodeAppEnvironment(): AppEnvironment {
|
||||
const quitHandlers: (() => void)[] = []
|
||||
// The main signal handler awaits runtime and browser teardown before process.exit.
|
||||
// Keep will-quit callbacks synchronous, but never let them pre-empt that async barrier.
|
||||
quitRegisteredHandlers = (): void => {
|
||||
const errors: unknown[] = []
|
||||
for (const handler of quitHandlers.splice(0)) {
|
||||
try {
|
||||
handler()
|
||||
} catch (error) {
|
||||
errors.push(error)
|
||||
}
|
||||
}
|
||||
// Why throw: a quit handler that failed may leave a writer running, which keeps the lock.
|
||||
if (errors.length > 0) {
|
||||
throw new AggregateError(errors, 'orcad_quit_handlers_failed')
|
||||
}
|
||||
}
|
||||
return {
|
||||
getPath: resolveOrcadPath,
|
||||
getAppPath: () => resolveOrcadInstallRoot(),
|
||||
getVersion: () => process.env.ORCA_VERSION ?? '0.0.0-orcad',
|
||||
// Why still true: consumers read this as "production build, not a dev checkout" —
|
||||
// it gates HTTPS-only skill downloads, the real CLI command name, and shell-PATH
|
||||
// hydration. Answering false to satisfy a path resolver would relax a security
|
||||
// posture. Layout questions must ask whether the app root is an asar archive
|
||||
// instead (see parcel-watcher-entry-path.ts).
|
||||
isPackaged: () => true,
|
||||
getCliLauncherPath: getOrcadCliLauncherPath,
|
||||
onWillQuit: (handler) => quitHandlers.push(handler),
|
||||
exit: (code = 0) => process.exit(code),
|
||||
// Why []: there are no Chromium processes on this host to measure.
|
||||
getAppMetrics: () => []
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Why not silently plaintext: `isEncryptionAvailable() === false` already makes every
|
||||
* caller fall back to unsealed storage, which is a security posture, not a detail.
|
||||
* `describeProtectionGap()` gives the reason a client can surface.
|
||||
*/
|
||||
function createNodeSecretStore(): SecretStore {
|
||||
return {
|
||||
isEncryptionAvailable: () => false,
|
||||
encryptString: () => {
|
||||
throw new Error('orcad_secret_sealing_unavailable')
|
||||
},
|
||||
decryptString: () => {
|
||||
throw new Error('orcad_secret_sealing_unavailable')
|
||||
},
|
||||
describeProtectionGap: () => describeOrcadSecretProtectionGap(process.platform)
|
||||
}
|
||||
}
|
||||
|
||||
export function installOrcadHostAdapters(): void {
|
||||
setAppEnvironment(createNodeAppEnvironment())
|
||||
setSecretStore(createNodeSecretStore())
|
||||
}
|
||||
@@ -13,7 +13,7 @@ vi.mock('../startup/hydrate-shell-path', () => hydration)
|
||||
|
||||
import { getAppEnvironment } from '../../shared/app-environment'
|
||||
import { hydrateShellPathForAgentDetection } from '../ipc/agent-detection-shell-path'
|
||||
import { installOrcadHostAdapters } from './orcad-entry'
|
||||
import { installOrcadHostAdapters } from './orcad-host-adapters'
|
||||
|
||||
describe('orcad PATH hydration on a WSL guest', () => {
|
||||
const platform = process.platform
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import path from 'node:path'
|
||||
import { installOrcadHostAdapters } from '../../../src/main/orcad/orcad-entry'
|
||||
import { installOrcadHostAdapters } from '../../../src/main/orcad/orcad-host-adapters'
|
||||
import type { Store } from '../../../src/main/persistence'
|
||||
import { createProfileStateStore } from '../../../src/main/persistence/profile-state/profile-state-store-factory'
|
||||
|
||||
|
||||
Reference in New Issue
Block a user