收口原生壳能力来源

新增共享 HostBridge capability profile,区分 Expo 移动通用、iOS 额外和 Tauri 桌面能力

移动壳能力清单改为引用共享 profile,入口 URL 类型支持 readonly 能力数组

两端配置检查和原生壳总门禁改为反查共享 profile,桌面 Rust 清单保持运行时镜像

补充 HostBridge profile 单测和 H5 readonly 能力合并类型兼容

同步 Expo/Tauri 壳方案、HostBridge 协议文档和项目决策记录
This commit is contained in:
2026-06-19 02:02:15 +08:00
parent a54210b0d1
commit 75cd4f1abc
12 changed files with 192 additions and 68 deletions
@@ -929,6 +929,10 @@ const sharedMethods = extractStringArrayExport(
sharedContractSource,
'HOST_BRIDGE_METHODS',
);
const sharedDesktopCapabilities = extractStringArrayExport(
sharedContractSource,
'HOST_BRIDGE_TAURI_DESKTOP_CAPABILITIES',
);
const sharedHostBridgeProtocol = extractTsStringConst(
sharedContractSource,
'HOST_BRIDGE_PROTOCOL',
@@ -1154,6 +1158,12 @@ if (unknownDesktopCapabilities.length > 0) {
);
}
assertSameList(
desktopCapabilities,
sharedDesktopCapabilities,
'desktop shell HostBridge capability profile',
);
for (const capability of sdkBackedCapabilities) {
if (desktopCapabilities.includes(capability)) {
throw new Error(
+26 -8
View File
@@ -481,6 +481,14 @@ const sharedMethods = extractStringArrayExport(
sharedContractSource,
'HOST_BRIDGE_METHODS',
);
const sharedMobileBaseCapabilities = extractStringArrayExport(
sharedContractSource,
'HOST_BRIDGE_EXPO_MOBILE_BASE_CAPABILITIES',
);
const sharedMobileIosCapabilities = extractStringArrayExport(
sharedContractSource,
'HOST_BRIDGE_EXPO_MOBILE_IOS_CAPABILITIES',
);
const sharedHostBridgeProtocol = extractStringConstExport(
sharedContractSource,
'HOST_BRIDGE_PROTOCOL',
@@ -498,14 +506,8 @@ const sharedPublicWebUrl = extractStringConstExport(
'HOST_BRIDGE_PUBLIC_WEB_URL',
);
const handledMobileMethods = extractMobileBridgeHandledMethods(dispatchSource);
const mobileCapabilities = extractStringArrayExport(
hostBridgeSource,
'MOBILE_HOST_CAPABILITIES',
);
const iosMobileCapabilities = extractStringArrayExport(
hostBridgeSource,
'IOS_MOBILE_HOST_CAPABILITIES',
);
const mobileCapabilities = sharedMobileBaseCapabilities;
const iosMobileCapabilities = sharedMobileIosCapabilities;
const mobileCapabilitySet = new Set(mobileCapabilities);
const iosMobileCapabilitySet = new Set(iosMobileCapabilities);
const sdkBackedCapabilities = ['auth.requestLogin', 'payment.request'];
@@ -553,6 +555,22 @@ for (const localBoundary of forbiddenLocalPayloadBoundaryDeclarations) {
}
}
for (const profileSource of [
'HOST_BRIDGE_EXPO_MOBILE_BASE_CAPABILITIES',
'HOST_BRIDGE_EXPO_MOBILE_IOS_CAPABILITIES',
]) {
if (!hostBridgeSource.includes(profileSource)) {
throw new Error(`mobile shell must use shared HostBridge profile ${profileSource}`);
}
}
if (
/export const MOBILE_HOST_CAPABILITIES[^=]*= \[/.test(hostBridgeSource) ||
/export const IOS_MOBILE_HOST_CAPABILITIES[^=]*= \[/.test(hostBridgeSource)
) {
throw new Error('mobile shell must not redeclare HostBridge capability profiles');
}
const unknownHandledMobileMethods = handledMobileMethods.filter(
(method) => !sharedMethods.includes(method),
);
@@ -1,37 +1,15 @@
import { Platform } from 'react-native';
import type { HostBridgeCapability } from '../../../../packages/shared/src/contracts/hostBridge';
import {
HOST_BRIDGE_EXPO_MOBILE_BASE_CAPABILITIES,
HOST_BRIDGE_EXPO_MOBILE_IOS_CAPABILITIES,
} from '../../../../packages/shared/src/contracts/hostBridge';
export const MOBILE_HOST_CAPABILITIES: HostBridgeCapability[] = [
'host.getRuntime',
'appearance.getColorScheme',
'host.events',
'app.lifecycle',
'share.open',
'share.setTarget',
'navigation.openNativePage',
'navigation.canGoBack',
'app.reloadWebView',
'app.openExternalUrl',
'network.status',
'network.statusChanged',
'clipboard.writeText',
'clipboard.readText',
'file.exportText',
'file.importText',
'file.exportImage',
'file.importImage',
'file.captureImage',
'file.importAudio',
'file.exportAudio',
'haptics.impact',
'notification.showLocal',
];
export const MOBILE_HOST_CAPABILITIES =
HOST_BRIDGE_EXPO_MOBILE_BASE_CAPABILITIES;
export const IOS_MOBILE_HOST_CAPABILITIES: HostBridgeCapability[] = [
...MOBILE_HOST_CAPABILITIES,
'app.setBadgeCount',
];
export const IOS_MOBILE_HOST_CAPABILITIES =
HOST_BRIDGE_EXPO_MOBILE_IOS_CAPABILITIES;
export function resolveMobileHostCapabilities(platform = Platform.OS) {
return platform === 'ios'
+1 -1
View File
@@ -9,7 +9,7 @@ import {
export type MobileShellUrlOptions = {
platform: Extract<NativeHostPlatform, 'ios' | 'android'>;
hostVersion: string;
capabilities: HostBridgeCapability[];
capabilities: readonly HostBridgeCapability[];
};
export const DEFAULT_MOBILE_SHELL_WEB_URL = HOST_BRIDGE_PUBLIC_WEB_URL;