Files
Genarrative/apps/desktop-shell/scripts/check-config.mjs
kdletters d67f9d5725 接入桌面壳文本文件导出能力
新增 HostBridge file.exportText 契约、文件名清洗和 H5 导出入口

Tauri 桌面壳通过受控 host_bridge_request 打开保存对话框并写入文本文件

Expo 移动壳对未接入的文件导出能力明确返回 unsupported

更新宿主壳方案、统一协议和项目共享决策记录
2026-06-17 23:02:01 +08:00

96 lines
3.0 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,file.exportText',
];
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"',
'"file.exportText"',
'tauri_plugin_dialog::init()',
'"copied_to_clipboard"',
'"file export cancelled"',
'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}`);
}
}