Files
Genarrative/apps/mobile-shell/src/host-bridge/protocol.ts
T
kdletters 1016472e2e 锁定移动壳未知异常响应
移动端 HostBridge 未知异常统一返回稳定 host_error 文案

移动壳协议测试覆盖普通 Error 不透出原生消息

移动壳配置检查反查未知异常不可透出 Error.message
2026-06-20 13:48:27 +08:00

113 lines
2.6 KiB
TypeScript

import {
HOST_BRIDGE_PROTOCOL,
HOST_BRIDGE_VERSION,
type HostBridgeError,
type HostBridgeMethod,
type HostBridgeRequest,
type HostBridgeResponse,
isHostBridgeMethod,
normalizeHostBridgeRequestId,
} from '../../../../packages/shared/src/contracts/hostBridge';
import type { MobileShellUrlOptions } from '../shell/url';
const HOST_BRIDGE_ERROR_CODES = new Set<HostBridgeError['code']>([
'invalid_request',
'unsupported_method',
'unsupported_capability',
'timeout',
'cancelled',
'host_error',
]);
export type MobileHostBridgeNavigation = {
allowedOrigin: string;
urlOptions: MobileShellUrlOptions;
openWebViewUrl: (url: string) => void;
reloadWebView: () => void;
};
export function unsupported(method: HostBridgeMethod): HostBridgeError {
return {
code: 'unsupported_method',
message: `${method} unsupported in mobile shell`,
};
}
export function invalidRequest(message: string): HostBridgeError {
return {
code: 'invalid_request',
message,
};
}
export function isHostBridgeRequest(value: unknown): value is HostBridgeRequest {
if (!value || typeof value !== 'object') {
return false;
}
const candidate = value as Partial<HostBridgeRequest>;
const requestId = normalizeHostBridgeRequestId(candidate.id);
return (
candidate.bridge === HOST_BRIDGE_PROTOCOL &&
candidate.version === HOST_BRIDGE_VERSION &&
requestId !== null &&
isHostBridgeMethod(candidate.method)
);
}
export function parseRequest(raw: string) {
try {
return JSON.parse(raw) as unknown;
} catch {
return null;
}
}
export function ok<Result>(
request: HostBridgeRequest,
result?: Result,
): HostBridgeResponse<Result> {
return {
bridge: HOST_BRIDGE_PROTOCOL,
version: HOST_BRIDGE_VERSION,
id: request.id,
ok: true,
result,
};
}
export function failure(
request: Pick<HostBridgeRequest, 'id'>,
error: HostBridgeError,
): HostBridgeResponse {
return {
bridge: HOST_BRIDGE_PROTOCOL,
version: HOST_BRIDGE_VERSION,
id: request.id,
ok: false,
error,
};
}
export function normalizeMobileHostBridgeError(error: unknown): HostBridgeError {
if (
error &&
typeof error === 'object' &&
'code' in error &&
'message' in error &&
typeof error.code === 'string' &&
HOST_BRIDGE_ERROR_CODES.has(error.code as HostBridgeError['code']) &&
typeof error.message === 'string'
) {
return {
code: error.code as HostBridgeError['code'],
message: error.message,
};
}
return {
code: 'host_error',
message: 'mobile host bridge request failed',
};
}