diff --git a/packages/common/metro/index.js b/packages/common/metro/index.js index 43509de..e4647bf 100644 --- a/packages/common/metro/index.js +++ b/packages/common/metro/index.js @@ -58,6 +58,58 @@ function applyBugCollect(metroConfig) { } } +/** 写入目标文件(仅在缺失或内容不一致时),返回是否发生写入。 */ +function syncFile(content, destPath, label) { + try { + if (fs.existsSync(destPath) && fs.readFileSync(destPath, 'utf-8').trim() === content) { + return false; + } + fs.mkdirSync(path.dirname(destPath), { recursive: true }); + fs.writeFileSync(destPath, content, 'utf-8'); + console.log(`[XuqmConfig] 已同步 .xuqmconfig → ${label}`); + return true; + } catch (e) { + console.warn(`[XuqmConfig] 同步 .xuqmconfig 到 ${label} 失败:${e.message}`); + return false; + } +} + +/** + * 单点放置:宿主只在 RN 侧放置一份 .xuqmconfig,构建/运行时自动同步到 + * 原生位置(Android assets/config,供 XuqmMergedProvider 自动初始化;iOS 资源目录)。 + * 缺失或内容不一致才复制,幂等。 + */ +function syncNativeConfig(projectRoot, content) { + const fileName = 'config.xuqmconfig'; + + // Android:原生 ContentProvider 扫描 assets/config 下的 .xuqmconfig + if (fs.existsSync(path.resolve(projectRoot, 'android'))) { + syncFile( + content, + path.resolve(projectRoot, 'android/app/src/main/assets/config', fileName), + 'android assets/config', + ); + } + + // iOS:复制到 app 资源目录(需在 Xcode「Copy Bundle Resources」中引用一次) + const iosDir = path.resolve(projectRoot, 'ios'); + if (fs.existsSync(iosDir)) { + try { + const appDir = fs + .readdirSync(iosDir, { withFileTypes: true }) + .filter( + (d) => d.isDirectory() && fs.existsSync(path.join(iosDir, d.name, 'Info.plist')), + ) + .map((d) => d.name)[0]; + if (appDir) { + syncFile(content, path.join(iosDir, appDir, 'config', fileName), `ios ${appDir}/config`); + } + } catch { + // 忽略 iOS 同步异常,不阻断打包 + } + } +} + function withXuqmConfig(metroConfig) { const projectRoot = metroConfig.projectRoot ?? process.cwd(); const configFile = findConfigFile(projectRoot); @@ -70,6 +122,9 @@ function withXuqmConfig(metroConfig) { // 读取加密配置内容 const encryptedContent = fs.readFileSync(configFile, 'utf-8').trim(); + // 单点放置:自动同步到原生 Android/iOS(缺失或不一致才复制) + syncNativeConfig(projectRoot, encryptedContent); + // 生成临时 TS 文件作为虚拟模块 const tmpDir = path.join(os.tmpdir(), 'xuqm-sdk-config'); fs.mkdirSync(tmpDir, { recursive: true });