080ebaedfd
移动 HostBridge 声明 navigation.openNativePage 并限制为同源 H5 route Expo WebView 将受控导航请求切换为新的 WebView URL 补充移动壳 HostBridge 与导航解析测试和配置守卫 更新宿主壳方案、统一协议和团队共享决策记录
49 lines
1.5 KiB
JavaScript
49 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',
|
|
]) {
|
|
if (!appSource.includes(snippet)) {
|
|
throw new Error(`mobile shell App missing ${snippet}`);
|
|
}
|
|
}
|