Skip to content

Commit 99fc323

Browse files
committed
fix(cli): validate connect timeout budget — reject NaN/0/negative before race
1 parent b5cdca7 commit 99fc323

2 files changed

Lines changed: 20 additions & 0 deletions

File tree

ui/cli/src/client/lifecycle.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ export const executeCommand = async (options: ExecuteOptions): Promise<void> =>
4646
activeClient = client
4747

4848
const budget = timeoutMs ?? UI_WEBSOCKET_REQUEST_TIMEOUT_MS
49+
if (!Number.isFinite(budget) || budget <= 0) {
50+
throw new Error(`Invalid timeout: ${String(budget)}ms (must be > 0)`)
51+
}
4952
const startTime = Date.now()
5053

5154
let connectTimeoutId: ReturnType<typeof setTimeout> | undefined

ui/cli/tests/lifecycle.test.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,21 @@ await describe('lifecycle', async () => {
3434
await it('should export executeCommand function', () => {
3535
assert.strictEqual(typeof executeCommand, 'function')
3636
})
37+
38+
await it('should reject executeCommand with NaN timeout', async () => {
39+
await assert.rejects(
40+
executeCommand({
41+
config: { host: 'localhost', port: 8080, protocol: 'ui', version: '0.0.1' },
42+
formatter: { error: () => undefined, output: () => undefined },
43+
payload: {},
44+
procedureName: 'listChargingStations' as never,
45+
timeoutMs: Number.NaN,
46+
}),
47+
(error: Error) => {
48+
assert.ok(error.message.includes('Invalid timeout'))
49+
assert.ok(error.message.includes('NaN'))
50+
return true
51+
}
52+
)
53+
})
3754
})

0 commit comments

Comments
 (0)