Files
Genarrative/apps/mobile-shell/scripts/check-config.mjs
kdletters 6f19e1c3ba 接入移动壳返回栈事件
移动壳声明 host.events 和 navigation.canGoBack 能力

Expo WebView 导航状态变化时向 H5 注入返回栈事件

H5 native_app transport 支持订阅 HostBridge 事件

补充事件订阅测试、移动壳能力测试和配置守卫

更新宿主壳方案和团队共享决策记录
2026-06-17 22:42:44 +08:00

51 lines
1.5 KiB
JavaScript

import fs from 'node:fs';
import { PNG } from 'pngjs';
const appConfigPath = new URL('../app.json', import.meta.url);
const appConfig = JSON.parse(fs.readFileSync(appConfigPath, 'utf8')).expo;
const appPath = new URL('../App.tsx', import.meta.url);
const appSource = fs.readFileSync(appPath, 'utf8');
const iconPath = new URL('../assets/icon.png', import.meta.url);
const icon = PNG.sync.read(fs.readFileSync(iconPath));
if (appConfig.scheme !== 'genarrative') {
throw new Error('mobile shell scheme must be genarrative');
}
if (appConfig.icon !== './assets/icon.png') {
throw new Error('mobile shell must use the real brand icon asset');
}
if (icon.width < 512 || icon.height < 512) {
throw new Error('mobile shell icon must be a production-size brand asset');
}
if (!appConfig.ios?.associatedDomains?.includes('applinks:app.genarrative.world')) {
throw new Error('mobile shell iOS associated domain is missing');
}
const androidFilter = appConfig.android?.intentFilters?.find((filter) =>
filter?.data?.some(
(entry) =>
entry?.scheme === 'https' &&
entry?.host === 'app.genarrative.world',
),
);
if (!androidFilter) {
throw new Error('mobile shell Android app link filter is missing');
}
for (const snippet of [
'Linking.getInitialURL()',
"Linking.addEventListener('url'",
'buildMobileShellUrlFromDeepLink',
'configureMobileHostBridgeNavigation',
'navigation.canGoBack',
'buildHostBridgeMessageScript',
]) {
if (!appSource.includes(snippet)) {
throw new Error(`mobile shell App missing ${snippet}`);
}
}