- xwebview: 下载支持公共Downloads/相册(CameraRoll懒加载)/JS进度/openFile;XWebViewView 新增内联 config prop(同屏多实例不污染全局) - bugcollect: startCapture 自动启用 HttpInterceptor + 按指纹滑动窗口限频 + setSampleRate 采样(降低服务端存储压力) - update: ignoreAppVersion/clearIgnoredAppVersion/getIgnoredAppVersion 客户端忽略版本(强制更新除外) - common/metro: withXuqmConfig 自动链式 withBugCollect(Release 包 sourcemap 自动上传) - push: 桥接完整原生 sdk-push(Android Kotlin + iOS Swift + JS 薄层),删除旧反射实现;单一 XuqmSDK.setUserInfo 驱动厂商检测/token/绑定 Co-Authored-By: Claude <noreply@anthropic.com>
109 行
3.3 KiB
JavaScript
109 行
3.3 KiB
JavaScript
'use strict';
|
||
|
||
/**
|
||
* Metro 插件:自动发现 .xuqmconfig 配置文件。
|
||
*
|
||
* 宿主只需将平台下载的 .xuqmconfig 文件放入 src/assets/config/,
|
||
* SDK 自动读取并完成初始化,无需重命名或创建 .ts 包装文件。
|
||
*
|
||
* 对齐 Android SDK 的 ConfigFileReader 逻辑:
|
||
* 优先 config.xuqmconfig,否则取第一个 *.xuqmconfig。
|
||
*
|
||
* @param {import('@react-native/metro-config').MetroConfig} metroConfig
|
||
* @returns {import('@react-native/metro-config').MetroConfig}
|
||
*/
|
||
const fs = require('fs');
|
||
const path = require('path');
|
||
const os = require('os');
|
||
|
||
const VIRTUAL_MODULE_ID = '@xuqm/autoinit-config';
|
||
const CONFIG_DIR_CANDIDATES = [
|
||
'src/assets/config',
|
||
'src/assets/xuqm',
|
||
'assets/config',
|
||
'assets/xuqm',
|
||
];
|
||
|
||
function findConfigFile(projectRoot) {
|
||
for (const dir of CONFIG_DIR_CANDIDATES) {
|
||
const absDir = path.resolve(projectRoot, dir);
|
||
if (!fs.existsSync(absDir)) continue;
|
||
|
||
const files = fs.readdirSync(absDir);
|
||
// 优先 config.xuqmconfig 或 config.xuqm
|
||
const preferred = files.find(
|
||
(f) => f === 'config.xuqmconfig' || f === 'config.xuqm',
|
||
);
|
||
if (preferred) {
|
||
return path.join(absDir, preferred);
|
||
}
|
||
// 否则取第一个 .xuqmconfig
|
||
const fallback = files.find((f) => f.endsWith('.xuqmconfig'));
|
||
if (fallback) {
|
||
return path.join(absDir, fallback);
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
function applyBugCollect(metroConfig) {
|
||
// 可选链式:安装了 @xuqm/rn-bugcollect 时,自动启用 Release 包 SourceMap 上传。
|
||
// 未安装则原样返回(不强制依赖)。
|
||
try {
|
||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||
const { withBugCollect } = require('@xuqm/rn-bugcollect/metro');
|
||
return typeof withBugCollect === 'function' ? withBugCollect(metroConfig) : metroConfig;
|
||
} catch {
|
||
return metroConfig;
|
||
}
|
||
}
|
||
|
||
function withXuqmConfig(metroConfig) {
|
||
const projectRoot = metroConfig.projectRoot ?? process.cwd();
|
||
const configFile = findConfigFile(projectRoot);
|
||
|
||
if (!configFile) {
|
||
// 未找到配置文件,返回原配置(autoInit 会静默跳过)
|
||
return applyBugCollect(metroConfig);
|
||
}
|
||
|
||
// 读取加密配置内容
|
||
const encryptedContent = fs.readFileSync(configFile, 'utf-8').trim();
|
||
|
||
// 生成临时 TS 文件作为虚拟模块
|
||
const tmpDir = path.join(os.tmpdir(), 'xuqm-sdk-config');
|
||
fs.mkdirSync(tmpDir, { recursive: true });
|
||
const virtualFile = path.join(tmpDir, 'autoinit-config.ts');
|
||
fs.writeFileSync(
|
||
virtualFile,
|
||
`// Auto-generated by @xuqm/rn-common/metro — do not edit\nexport const ENCRYPTED_CONFIG = ${JSON.stringify(encryptedContent)};\n`,
|
||
'utf-8',
|
||
);
|
||
|
||
// 拦截模块解析,将 @xuqm/autoinit-config 指向虚拟文件
|
||
const existingResolveRequest = metroConfig.resolver?.resolveRequest;
|
||
|
||
return applyBugCollect({
|
||
...metroConfig,
|
||
resolver: {
|
||
...metroConfig.resolver,
|
||
resolveRequest: (context, moduleName, platform) => {
|
||
if (moduleName === VIRTUAL_MODULE_ID) {
|
||
return {
|
||
type: 'sourceFile',
|
||
filePath: virtualFile,
|
||
};
|
||
}
|
||
|
||
if (existingResolveRequest) {
|
||
return existingResolveRequest(context, moduleName, platform);
|
||
}
|
||
|
||
return context.resolveRequest(context, moduleName, platform);
|
||
},
|
||
},
|
||
});
|
||
}
|
||
|
||
module.exports = { withXuqmConfig };
|