HostBridge 契约新增 app.setTitle 方法和标题 payload Tauri 桌面壳通过主窗口 API 同步非空窗口标题 桌面壳能力清单和配置守卫声明 app.setTitle 补充标题校验测试并更新宿主壳方案和团队共享决策记录
93 lines
2.9 KiB
JavaScript
93 lines
2.9 KiB
JavaScript
import fs from 'node:fs';
|
|
|
|
const configPath = new URL('../src-tauri/tauri.conf.json', import.meta.url);
|
|
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
const capabilityPath = new URL(
|
|
'../src-tauri/capabilities/main.json',
|
|
import.meta.url,
|
|
);
|
|
const capability = JSON.parse(fs.readFileSync(capabilityPath, 'utf8'));
|
|
const buildScriptPath = new URL('../src-tauri/build.rs', import.meta.url);
|
|
const buildScript = fs.readFileSync(buildScriptPath, 'utf8');
|
|
const iconPath = new URL('../src-tauri/icons/icon.png', import.meta.url);
|
|
|
|
if (config.build?.frontendDist !== '../../../dist') {
|
|
throw new Error('desktop shell must package the root H5 dist');
|
|
}
|
|
|
|
if (config.build?.beforeBuildCommand !== 'npm --prefix ../.. run build:raw && npm run typecheck') {
|
|
throw new Error('desktop shell build command must run from apps/desktop-shell');
|
|
}
|
|
|
|
const [mainWindow] = config.app?.windows ?? [];
|
|
if (!mainWindow || mainWindow.create !== false) {
|
|
throw new Error('desktop shell must create the main window from Rust setup');
|
|
}
|
|
|
|
if (!config.bundle?.icon?.includes('icons/icon.png')) {
|
|
throw new Error('desktop shell must use the real brand icon asset');
|
|
}
|
|
|
|
const requiredUrlParts = [
|
|
'clientRuntime=native_app',
|
|
'clientType=native_app',
|
|
'hostShell=tauri_desktop',
|
|
'hostPlatform=unknown',
|
|
'bridgeVersion=1',
|
|
'hostCapabilities=host.getRuntime,share.open,share.setTarget,app.openExternalUrl,app.setTitle,clipboard.writeText',
|
|
];
|
|
|
|
for (const part of requiredUrlParts) {
|
|
if (!String(mainWindow.url ?? '').includes(part)) {
|
|
throw new Error(`desktop shell main window URL missing ${part}`);
|
|
}
|
|
if (!String(config.build?.devUrl ?? '').includes(part)) {
|
|
throw new Error(`desktop shell dev URL missing ${part}`);
|
|
}
|
|
}
|
|
|
|
const requiredPermissions = [
|
|
'core:default',
|
|
'allow-host-bridge-request',
|
|
];
|
|
const requiredBuildCommands = ['host_bridge_request'];
|
|
const requiredMainSnippets = [
|
|
'tauri_plugin_clipboard_manager::init()',
|
|
'"share.open"',
|
|
'"share.setTarget"',
|
|
'"app.setTitle"',
|
|
'"clipboard.writeText"',
|
|
'"copied_to_clipboard"',
|
|
'set_title',
|
|
];
|
|
|
|
for (const permission of requiredPermissions) {
|
|
if (!capability.permissions?.includes(permission)) {
|
|
throw new Error(`desktop shell capability missing ${permission}`);
|
|
}
|
|
}
|
|
|
|
for (const command of requiredBuildCommands) {
|
|
if (!buildScript.includes(command)) {
|
|
throw new Error(`desktop shell build manifest missing ${command}`);
|
|
}
|
|
}
|
|
|
|
if (buildScript.includes('resolve_desktop_shell_runtime')) {
|
|
throw new Error('desktop shell build manifest exposes an unused runtime command');
|
|
}
|
|
|
|
const icon = fs.readFileSync(iconPath);
|
|
if (icon.length < 10000) {
|
|
throw new Error('desktop shell icon must use a real brand asset');
|
|
}
|
|
|
|
const mainPath = new URL('../src-tauri/src/main.rs', import.meta.url);
|
|
const main = fs.readFileSync(mainPath, 'utf8');
|
|
|
|
for (const snippet of requiredMainSnippets) {
|
|
if (!main.includes(snippet)) {
|
|
throw new Error(`desktop shell Rust host bridge missing ${snippet}`);
|
|
}
|
|
}
|