Files
Genarrative/apps/mobile-shell/src/host-bridge/bridge.ts
T
kdletters 071faa482c 统一 Rust 与 TypeScript 格式化门禁
纳入 AGC Cargo workspace 的统一 rustfmt 检查与格式化入口

完成项目 TypeScript/Prettier 与 Rust 全量格式化

修复 Pingora expected executable 门禁的空白敏感误报

同步开发运维文档与 AGC skill pack 格式化忽略规则
2026-09-01 16:28:34 +08:00

90 lines
2.5 KiB
TypeScript

import {
HOST_BRIDGE_RESPONSE_CACHE_MAX,
type HostBridgeRequest,
type HostBridgeResponse,
normalizeHostBridgeRequestId,
} from '../../../../packages/shared/src/contracts/hostBridge';
import {
dispatchMobileHostBridgeRequest,
resetMobileHostBridgeDispatchForTest,
} from './dispatch';
import {
failure,
invalidRequest,
isHostBridgeRequest,
normalizeMobileHostBridgeError,
parseRequest,
} from './protocol';
export {
IOS_MOBILE_HOST_CAPABILITIES,
MOBILE_HOST_CAPABILITIES,
resolveMobileHostCapabilities,
} from './capabilities';
export { configureMobileHostBridgeNavigation } from './dispatch';
const completedHostBridgeResponses = new Map<string, HostBridgeResponse>();
const inFlightHostBridgeResponses = new Map<
string,
Promise<HostBridgeResponse>
>();
function rememberHostBridgeResponse(response: HostBridgeResponse) {
completedHostBridgeResponses.set(response.id, response);
if (completedHostBridgeResponses.size > HOST_BRIDGE_RESPONSE_CACHE_MAX) {
const oldestRequestId = completedHostBridgeResponses.keys().next().value;
if (oldestRequestId) {
completedHostBridgeResponses.delete(oldestRequestId);
}
}
return response;
}
async function resolveMobileHostBridgeResponse(request: HostBridgeRequest) {
const completedResponse = completedHostBridgeResponses.get(request.id);
if (completedResponse) {
return completedResponse;
}
const inFlightResponse = inFlightHostBridgeResponses.get(request.id);
if (inFlightResponse) {
return await inFlightResponse;
}
const responsePromise = dispatchMobileHostBridgeRequest(request)
.catch((error: unknown) =>
failure(request, normalizeMobileHostBridgeError(error)),
)
.then(rememberHostBridgeResponse);
inFlightHostBridgeResponses.set(request.id, responsePromise);
try {
return await responsePromise;
} finally {
inFlightHostBridgeResponses.delete(request.id);
}
}
export async function handleMobileHostBridgeMessage(
rawMessage: string,
sendResponse: (response: HostBridgeResponse) => void,
) {
const parsed = parseRequest(rawMessage);
if (!isHostBridgeRequest(parsed)) {
sendResponse(
failure({ id: 'invalid' }, invalidRequest('invalid host bridge request')),
);
return;
}
parsed.id = normalizeHostBridgeRequestId(parsed.id) ?? parsed.id;
sendResponse(await resolveMobileHostBridgeResponse(parsed));
}
export function resetMobileHostBridgeForTest() {
resetMobileHostBridgeDispatchForTest();
completedHostBridgeResponses.clear();
inFlightHostBridgeResponses.clear();
}