补齐桌面壳能力流程门禁
根级原生壳检查反查 Tauri 关键能力真实流程 宿主壳方案文档记录桌面能力到实现与测试合同 项目记忆同步 Tauri 能力真实链路约束
This commit is contained in:
@@ -276,7 +276,7 @@ const mobileCapabilityFlowContracts = [
|
||||
'apps/mobile-shell/scripts/check-expo-config.mjs',
|
||||
'android.permission.POST_NOTIFICATIONS',
|
||||
],
|
||||
[nativeShellPlanPath, 'Expo 移动壳的关键能力'],
|
||||
[nativeShellPlanPath, 'Expo 移动壳和 Tauri 桌面壳的关键能力'],
|
||||
],
|
||||
tests: [
|
||||
'apps/mobile-shell/src/host-bridge/notifications.test.ts',
|
||||
@@ -307,7 +307,7 @@ const mobileCapabilityFlowContracts = [
|
||||
'ImagePicker.launchCameraAsync',
|
||||
],
|
||||
['apps/mobile-shell/scripts/check-config.mjs', 'file.captureImage'],
|
||||
[nativeShellPlanPath, 'Expo 移动壳的关键能力'],
|
||||
[nativeShellPlanPath, 'Expo 移动壳和 Tauri 桌面壳的关键能力'],
|
||||
],
|
||||
tests: [
|
||||
'apps/mobile-shell/src/host-bridge/files.test.ts',
|
||||
@@ -340,7 +340,7 @@ const mobileCapabilityFlowContracts = [
|
||||
],
|
||||
['apps/mobile-shell/src/shell/QrScannerOverlay.tsx', 'CameraView'],
|
||||
['apps/mobile-shell/scripts/check-config.mjs', 'scanner.scanQrCode'],
|
||||
[nativeShellPlanPath, 'Expo 移动壳的关键能力'],
|
||||
[nativeShellPlanPath, 'Expo 移动壳和 Tauri 桌面壳的关键能力'],
|
||||
],
|
||||
tests: [
|
||||
'apps/mobile-shell/src/host-bridge/scanner.test.ts',
|
||||
@@ -371,7 +371,7 @@ const mobileCapabilityFlowContracts = [
|
||||
"logMobileHostEventFailure('network.statusChanged', error)",
|
||||
],
|
||||
['apps/mobile-shell/scripts/check-config.mjs', 'network.statusChanged'],
|
||||
[nativeShellPlanPath, 'Expo 移动壳的关键能力'],
|
||||
[nativeShellPlanPath, 'Expo 移动壳和 Tauri 桌面壳的关键能力'],
|
||||
],
|
||||
tests: [
|
||||
'apps/mobile-shell/src/shell/network.test.ts',
|
||||
@@ -395,7 +395,7 @@ const mobileCapabilityFlowContracts = [
|
||||
'normalizeHostBridgeShareOpenPayload',
|
||||
],
|
||||
['apps/mobile-shell/scripts/check-config.mjs', 'share.open'],
|
||||
[nativeShellPlanPath, 'Expo 移动壳的关键能力'],
|
||||
[nativeShellPlanPath, 'Expo 移动壳和 Tauri 桌面壳的关键能力'],
|
||||
],
|
||||
tests: [
|
||||
'apps/mobile-shell/src/host-bridge/share.test.ts',
|
||||
@@ -403,6 +403,207 @@ const mobileCapabilityFlowContracts = [
|
||||
],
|
||||
},
|
||||
];
|
||||
const desktopCapabilityFlowContracts = [
|
||||
{
|
||||
capability: 'notification.showLocal',
|
||||
files: [
|
||||
'apps/desktop-shell/src-tauri/Cargo.toml',
|
||||
'apps/desktop-shell/src-tauri/src/app.rs',
|
||||
'apps/desktop-shell/src-tauri/src/host_bridge/dispatch.rs',
|
||||
'apps/desktop-shell/src-tauri/src/host_bridge/notifications.rs',
|
||||
'apps/desktop-shell/scripts/check-config.mjs',
|
||||
nativeShellPlanPath,
|
||||
],
|
||||
snippets: [
|
||||
[
|
||||
'apps/desktop-shell/src-tauri/Cargo.toml',
|
||||
'tauri-plugin-notification',
|
||||
],
|
||||
[
|
||||
'apps/desktop-shell/src-tauri/src/app.rs',
|
||||
'tauri_plugin_notification::init()',
|
||||
],
|
||||
[
|
||||
'apps/desktop-shell/src-tauri/src/host_bridge/dispatch.rs',
|
||||
'show_desktop_local_notification(&app, &request)',
|
||||
],
|
||||
[
|
||||
'apps/desktop-shell/src-tauri/src/host_bridge/notifications.rs',
|
||||
'app.notification()',
|
||||
],
|
||||
[
|
||||
'apps/desktop-shell/src-tauri/src/host_bridge/notifications.rs',
|
||||
'request_permission()',
|
||||
],
|
||||
[
|
||||
'apps/desktop-shell/src-tauri/src/host_bridge/notifications.rs',
|
||||
'notification.show()',
|
||||
],
|
||||
[
|
||||
'apps/desktop-shell/scripts/check-config.mjs',
|
||||
'notification.showLocal',
|
||||
],
|
||||
[nativeShellPlanPath, 'Tauri 壳'],
|
||||
],
|
||||
},
|
||||
{
|
||||
capability: 'file.importDocument',
|
||||
files: [
|
||||
'apps/desktop-shell/src-tauri/Cargo.toml',
|
||||
'apps/desktop-shell/src-tauri/src/app.rs',
|
||||
'apps/desktop-shell/src-tauri/src/host_bridge/dispatch.rs',
|
||||
'apps/desktop-shell/src-tauri/src/host_bridge/files.rs',
|
||||
'apps/desktop-shell/src-tauri/src/host_bridge/file_payloads.rs',
|
||||
'apps/desktop-shell/scripts/check-config.mjs',
|
||||
nativeShellPlanPath,
|
||||
],
|
||||
snippets: [
|
||||
['apps/desktop-shell/src-tauri/Cargo.toml', 'tauri-plugin-dialog'],
|
||||
['apps/desktop-shell/src-tauri/src/app.rs', 'tauri_plugin_dialog::init()'],
|
||||
[
|
||||
'apps/desktop-shell/src-tauri/src/host_bridge/dispatch.rs',
|
||||
'import_desktop_host_bridge_document_file(&app, &request).await',
|
||||
],
|
||||
[
|
||||
'apps/desktop-shell/src-tauri/src/host_bridge/files.rs',
|
||||
'add_filter(\n "Document"',
|
||||
],
|
||||
[
|
||||
'apps/desktop-shell/src-tauri/src/host_bridge/files.rs',
|
||||
'blocking_pick_file()',
|
||||
],
|
||||
[
|
||||
'apps/desktop-shell/src-tauri/src/host_bridge/files.rs',
|
||||
'import_document_file_payload(path)',
|
||||
],
|
||||
[
|
||||
'apps/desktop-shell/src-tauri/src/host_bridge/file_payloads.rs',
|
||||
'import_document_file_payload',
|
||||
],
|
||||
[
|
||||
'apps/desktop-shell/scripts/check-config.mjs',
|
||||
'file.importDocument',
|
||||
],
|
||||
[nativeShellPlanPath, 'Tauri 壳'],
|
||||
],
|
||||
},
|
||||
{
|
||||
capability: 'file.exportImage',
|
||||
files: [
|
||||
'apps/desktop-shell/src-tauri/Cargo.toml',
|
||||
'apps/desktop-shell/src-tauri/src/app.rs',
|
||||
'apps/desktop-shell/src-tauri/src/host_bridge/dispatch.rs',
|
||||
'apps/desktop-shell/src-tauri/src/host_bridge/files.rs',
|
||||
'apps/desktop-shell/src-tauri/src/host_bridge/file_payloads.rs',
|
||||
'apps/desktop-shell/scripts/check-config.mjs',
|
||||
nativeShellPlanPath,
|
||||
],
|
||||
snippets: [
|
||||
['apps/desktop-shell/src-tauri/Cargo.toml', 'tauri-plugin-dialog'],
|
||||
['apps/desktop-shell/src-tauri/src/app.rs', 'tauri_plugin_dialog::init()'],
|
||||
[
|
||||
'apps/desktop-shell/src-tauri/src/host_bridge/dispatch.rs',
|
||||
'export_desktop_host_bridge_image_file(&app, &request).await',
|
||||
],
|
||||
[
|
||||
'apps/desktop-shell/src-tauri/src/host_bridge/files.rs',
|
||||
'add_filter("Image", &["png", "jpg", "jpeg", "webp"])',
|
||||
],
|
||||
[
|
||||
'apps/desktop-shell/src-tauri/src/host_bridge/files.rs',
|
||||
'blocking_save_file()',
|
||||
],
|
||||
[
|
||||
'apps/desktop-shell/src-tauri/src/host_bridge/files.rs',
|
||||
'write_export_bytes_file(path, bytes)',
|
||||
],
|
||||
[
|
||||
'apps/desktop-shell/src-tauri/src/host_bridge/file_payloads.rs',
|
||||
'export_image_payload',
|
||||
],
|
||||
['apps/desktop-shell/scripts/check-config.mjs', 'file.exportImage'],
|
||||
[nativeShellPlanPath, 'Tauri 壳'],
|
||||
],
|
||||
},
|
||||
{
|
||||
capability: 'file.imageDropped',
|
||||
files: [
|
||||
'apps/desktop-shell/src-tauri/src/app.rs',
|
||||
'apps/desktop-shell/src-tauri/src/shell/file_drop.rs',
|
||||
'apps/desktop-shell/src-tauri/src/shell/events.rs',
|
||||
'apps/desktop-shell/scripts/check-config.mjs',
|
||||
nativeShellPlanPath,
|
||||
],
|
||||
snippets: [
|
||||
[
|
||||
'apps/desktop-shell/src-tauri/src/app.rs',
|
||||
'register_desktop_file_drop_events(&window)',
|
||||
],
|
||||
[
|
||||
'apps/desktop-shell/src-tauri/src/shell/file_drop.rs',
|
||||
'DragDropEvent::Drop',
|
||||
],
|
||||
[
|
||||
'apps/desktop-shell/src-tauri/src/shell/file_drop.rs',
|
||||
'host_bridge_event_script("file.imageDropped", payload)',
|
||||
],
|
||||
[
|
||||
'apps/desktop-shell/src-tauri/src/shell/file_drop.rs',
|
||||
'import_image_file_payload(path.clone(), "dropped", Some(position))',
|
||||
],
|
||||
[
|
||||
'apps/desktop-shell/src-tauri/src/shell/events.rs',
|
||||
'file.imageDropped',
|
||||
],
|
||||
['apps/desktop-shell/scripts/check-config.mjs', 'file.imageDropped'],
|
||||
[nativeShellPlanPath, 'Tauri 壳'],
|
||||
],
|
||||
},
|
||||
{
|
||||
capability: 'share.open',
|
||||
files: [
|
||||
'apps/desktop-shell/src-tauri/Cargo.toml',
|
||||
'apps/desktop-shell/src-tauri/src/app.rs',
|
||||
'apps/desktop-shell/src-tauri/src/host_bridge/dispatch.rs',
|
||||
'apps/desktop-shell/src-tauri/src/host_bridge/share.rs',
|
||||
'apps/desktop-shell/src-tauri/src/host_bridge/clipboard.rs',
|
||||
'apps/desktop-shell/scripts/check-config.mjs',
|
||||
nativeShellPlanPath,
|
||||
],
|
||||
snippets: [
|
||||
[
|
||||
'apps/desktop-shell/src-tauri/Cargo.toml',
|
||||
'tauri-plugin-clipboard-manager',
|
||||
],
|
||||
[
|
||||
'apps/desktop-shell/src-tauri/src/app.rs',
|
||||
'tauri_plugin_clipboard_manager::init()',
|
||||
],
|
||||
[
|
||||
'apps/desktop-shell/src-tauri/src/host_bridge/dispatch.rs',
|
||||
'open_desktop_host_bridge_share(&app, &request)',
|
||||
],
|
||||
[
|
||||
'apps/desktop-shell/src-tauri/src/host_bridge/share.rs',
|
||||
'normalize_public_share_url',
|
||||
],
|
||||
[
|
||||
'apps/desktop-shell/src-tauri/src/host_bridge/share.rs',
|
||||
'write_desktop_clipboard_text(app, &share_text)',
|
||||
],
|
||||
[
|
||||
'apps/desktop-shell/src-tauri/src/host_bridge/share.rs',
|
||||
'"action": "copied_to_clipboard"',
|
||||
],
|
||||
[
|
||||
'apps/desktop-shell/src-tauri/src/host_bridge/clipboard.rs',
|
||||
'write_desktop_clipboard_text',
|
||||
],
|
||||
['apps/desktop-shell/scripts/check-config.mjs', 'share.open'],
|
||||
[nativeShellPlanPath, 'Tauri 壳'],
|
||||
],
|
||||
},
|
||||
];
|
||||
const h5NativeAppRouteFlowContracts = [
|
||||
{
|
||||
route: '/child-motion-demo',
|
||||
@@ -2267,6 +2468,47 @@ function assertExpoMobileCapabilityFlows() {
|
||||
}
|
||||
}
|
||||
|
||||
function assertTauriDesktopCapabilityFlows() {
|
||||
const sharedContractSource = fs.readFileSync(sharedHostBridgeContractPath, 'utf8');
|
||||
const declaredCapabilities = extractTsStringArray(
|
||||
sharedContractSource,
|
||||
'HOST_BRIDGE_TAURI_DESKTOP_CAPABILITIES',
|
||||
);
|
||||
const declaredCapabilitySet = new Set(declaredCapabilities);
|
||||
const contractedCapabilities = desktopCapabilityFlowContracts.map(
|
||||
({ capability }) => capability,
|
||||
);
|
||||
|
||||
assertUniqueList(
|
||||
contractedCapabilities,
|
||||
'Tauri desktop capability flow contracts',
|
||||
);
|
||||
|
||||
for (const contract of desktopCapabilityFlowContracts) {
|
||||
if (!declaredCapabilitySet.has(contract.capability)) {
|
||||
throw new Error(
|
||||
`Tauri desktop capability flow contract declared for missing capability: ${contract.capability}`,
|
||||
);
|
||||
}
|
||||
|
||||
for (const filePath of contract.files) {
|
||||
if (!fs.existsSync(filePath)) {
|
||||
throw new Error(
|
||||
`Tauri desktop ${contract.capability} flow file is missing: ${filePath}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
for (const [filePath, snippet] of contract.snippets) {
|
||||
assertFileIncludesSnippet(
|
||||
filePath,
|
||||
snippet,
|
||||
`Tauri desktop ${contract.capability} flow`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function assertH5NativeAppRouteFlows() {
|
||||
const h5HostBridgeTestSet = new Set(h5HostBridgeTests);
|
||||
for (const contract of h5NativeAppRouteFlowContracts) {
|
||||
@@ -2764,6 +3006,9 @@ assertWechatMiniProgramCapabilityFlows();
|
||||
console.log('[check:native-shells] expo-mobile-capability-flows');
|
||||
assertExpoMobileCapabilityFlows();
|
||||
|
||||
console.log('[check:native-shells] tauri-desktop-capability-flows');
|
||||
assertTauriDesktopCapabilityFlows();
|
||||
|
||||
console.log('[check:native-shells] h5-native-app-route-flows');
|
||||
assertH5NativeAppRouteFlows();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user