Files
Genarrative/apps/mobile-shell/scripts/check-config.mjs
kdletters 02a475d652 接入 Expo 移动壳深链入口
新增移动壳 deep link 到同源 H5 路径的解析与运行时监听

配置移动壳真实品牌图标、iOS associated domain 和 Android app link

补充移动壳配置守门、单测和宿主壳文档记忆
2026-06-17 22:04:18 +08:00

48 lines
1.4 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',
]) {
if (!appSource.includes(snippet)) {
throw new Error(`mobile shell App missing ${snippet}`);
}
}