XuqmGroup-RNSDK/README.md
XuqmGroup ab30b28f3d feat: v0.3.0 — 自动初始化 + 插件更新 + 脚手架工具
common:
- 新增 autoInit.ts 自动初始化(对齐 Android ContentProvider 模式)
- 新增 configCrypto.ts 内置配置文件解密
- XuqmSDK 新增 initWithConfigFile / setUserInfo / getUserInfo
- 新增 crypto-types.d.ts Web Crypto 类型声明

update:
- 重写 UpdateSDK:checkAppUpdate / checkPluginUpdate / checkAndCachePlugin
- 移除 checkAndPromptAppUpdate(SDK 不做 UI)
- 新增插件脚手架 create-plugin.mjs
- 重命名 RnUpdateInfo → PluginUpdateInfo

license:
- crypto.ts 支持 XUQM-CONFIG-V1 + XUQM-LICENSE-V1 双格式
- 新增 decryptConfigFile 导出

docs:
- 重写 README.md
- 新增 docs/SDK-API参考.md
- 新增 docs/插件脚手架.md
- 新增 docs/配置文件规范.md
2026-06-15 01:44:20 +08:00

360 行
12 KiB
Markdown

# XuqmGroup React Native SDK
Modular React Native SDK providing IM, Push, App/Plugin Update, WebView, and License management for XuqmGroup platform applications.
## Table of Contents
- [Overview](#overview)
- [Package Structure](#package-structure)
- [Installation](#installation)
- [Quick Start](#quick-start)
- [Package Details](#package-details)
- [Development](#development)
- [Plugin Scaffolding](#plugin-scaffolding)
---
## Overview
`@xuqm/rn-sdk` is the meta-package that re-exports all sub-modules. It provides a unified `XuqmSDK` entry point with coordinated login/logout that wires up IM, Push, and token management in a single call.
You can install the meta-package for full functionality, or pick individual packages as needed.
**Peer Dependencies** (required in host app):
| Package | Version |
|---------|---------|
| `react` | >= 18.0.0 |
| `react-native` | >= 0.76.0 |
| `@react-native-async-storage/async-storage` | >= 1.21.0 |
---
## Package Structure
```
XuqmGroup-RNSDK/ # @xuqm/rn-sdk (meta-package, private)
├── src/
│ ├── index.ts # Re-exports all sub-packages
│ └── sdk.ts # Unified login / logout
├── packages/
│ ├── common/ @xuqm/rn-common # Init, network, device, token, HTTP, auto-init
│ ├── im/ @xuqm/rn-im # IM messaging (WebSocket/STOMP + WatermelonDB)
│ ├── push/ @xuqm/rn-push # Multi-vendor push registration
│ ├── update/ @xuqm/rn-update # App update check + RN plugin hot-update
│ ├── xwebview/ @xuqm/rn-xwebview # Enhanced WebView with JSBridge
│ └── license/ @xuqm/rn-license # Encrypted license file decryption & verification
```
All packages are at version **0.2.2**.
---
## Installation
### 1. Configure the npm registry
```bash
# In your host project root
cat > .npmrc << 'EOF'
registry=https://nexus.xuqinmin.com/repository/npm/
legacy-peer-deps=true
EOF
```
### 2. Install
**Option A -- Meta-package (all modules):**
```bash
yarn add @xuqm/rn-sdk
yarn add @react-native-async-storage/async-storage
```
**Option B -- Individual packages:**
```bash
yarn add @xuqm/rn-common @xuqm/rn-im @xuqm/rn-push @xuqm/rn-update @xuqm/rn-xwebview @xuqm/rn-license
yarn add @react-native-async-storage/async-storage
```
### 3. Install optional peer dependencies
```bash
# IM module (local database)
yarn add @nozbe/watermelondb
# XWebView module
yarn add react-native-webview react-native-blob-util react-native-svg
# License / encrypted config
yarn add react-native-quick-crypto
```
---
## Quick Start
### Zero-config initialization (recommended)
Place an encrypted `.xuqmconfig` file (XUQM-CONFIG-V1 format) in your project, then add a Metro alias so the SDK can auto-discover it:
```js
// metro.config.js
const { getDefaultConfig } = require('metro-config');
module.exports = (async () => {
const config = await getDefaultConfig(__dirname);
config.resolver.extraNodeModules = {
'@xuqm/autoinit-config': './path/to/your.xuqmconfig',
};
return config;
})();
```
That is it. When `@xuqm/rn-common` is imported, it silently calls `XuqmSDK.initWithConfigFile()` using the encrypted file. No explicit init code needed.
### Manual initialization
```ts
import { XuqmSDK } from '@xuqm/rn-sdk';
// Init with appKey (fetches config from server)
await XuqmSDK.initialize({ appKey: 'your-app-key' });
// Login (wires up IM + Push automatically)
await XuqmSDK.login({ userId: 'user123', userSig: '...' });
// Logout
await XuqmSDK.logout();
```
### Using individual modules
```ts
import { ImSDK } from '@xuqm/rn-im';
import { PushSDK } from '@xuqm/rn-push';
import { UpdateSDK } from '@xuqm/rn-update';
import { XWebViewScreen } from '@xuqm/rn-xwebview';
```
---
## Package Details
### @xuqm/rn-common
Core module. Handles SDK initialization, HTTP requests, token persistence, device identification, and auto-initialization from encrypted config files.
| Export | Description |
|--------|-------------|
| `XuqmSDK.initialize(opts)` | Init with `appKey`, fetches remote config |
| `XuqmSDK.initWithConfigFile(encrypted)` | Init from `XUQM-CONFIG-V1` encrypted file |
| `XuqmSDK.initializeFromLicense(licenseFile)` | Init from decrypted license data |
| `XuqmSDK.awaitInitialization()` | Wait for async init to complete |
| `XuqmSDK.setUserId / getUserId` | Manage current user ID |
| `XuqmSDK.setUserInfo / getUserInfo` | Manage current user profile |
| `apiRequest(url, options?)` | HTTP request with Bearer token auth |
| `configureHttp(opts)` | Override HTTP base URL or headers |
| `getDeviceId()` | Stable per-install UUID |
| `getDeviceInfo()` | Device brand/model/OS info |
| `detectPushVendor()` | Detect push vendor from device brand |
| `ScaledImage` | Image component with aspect-ratio scaling |
| `isInitialized()` | Check if SDK is ready |
| `getConfig()` | Get resolved config |
**Auto-init mechanism:** On import, `autoInit.ts` tries `require('@xuqm/autoinit-config')`. If the Metro alias is configured, it decrypts the file and calls `initWithConfigFile` silently. If the alias is not configured, it skips without error.
**Encrypted config format:** `XUQM-CONFIG-V1.{base64url-salt}.{base64url-iv}.{base64url-ciphertext}` -- decrypted via PBKDF2 (120k iterations, SHA-256) + AES-256-GCM using `react-native-quick-crypto`.
---
### @xuqm/rn-im
Full-featured IM module. WebSocket/STOMP transport with WatermelonDB local persistence. Supports single and group chat with 15 message types.
**Message types:** `TEXT`, `IMAGE`, `VIDEO`, `AUDIO`, `FILE`, `CUSTOM`, `LOCATION`, `NOTIFY`, `RICH_TEXT`, `CALL_AUDIO`, `CALL_VIDEO`, `QUOTE`, `MERGE`, `REVOKED`, `FORWARD`
| Export | Description |
|--------|-------------|
| `ImSDK.login(userId, userSig)` | Connect to IM server |
| `ImSDK.disconnect()` | Disconnect |
| `ImSDK.sendMessage(params)` | Send a message |
| `ImSDK.getConversations()` | List conversations |
| `ImSDK.getHistory(query)` | Fetch message history |
| `ImSDK.createGroup(...)` | Create a group |
| `ImSDK.joinGroup(groupId)` | Join a group |
| `ImSDK.getGroupInfo(groupId)` | Get group details |
| `ImSDK.getGroupMembers(groupId)` | List group members |
| `listFriends / addFriend / removeFriend` | Friend management |
| `setFriendGroup / listFriendGroups` | Friend grouping |
| `checkBlacklist` | Blacklist check |
| `searchUsers / searchGroups / searchMessages` | Search |
| `editMessage` | Edit a sent message |
| `setConversationHidden / setConversationGroup` | Conversation management |
| `locateHistoryPage / locateGroupHistoryPage` | Jump to specific history page |
| `syncOfflineMessages / offlineMessageCount` | Offline message handling |
| `ImClient` | Low-level STOMP client |
| `ImDatabase` | WatermelonDB wrapper |
| `uploadFile` | File upload for IM |
**Additional peer dependency:** `@nozbe/watermelondb >= 0.27.0`
---
### @xuqm/rn-push
Multi-vendor push registration. Automatically detects the device vendor (Huawei, Xiaomi, OPPO, vivo, Honor, FCM, APNS) and bridges to the native push module.
| Export | Description |
|--------|-------------|
| `PushSDK.initialize(userId?)` | Initialize push and register device token |
| `PushSDK.registerToken(userId, token, vendor?)` | Register a push token with server |
| `PushSDK.unregisterToken(userId)` | Unregister push token |
| `PushSDK.setDeviceToken(token, vendor?)` | Manually set device token |
| `PushSDK.onPushToken(callback)` | Listen for push token updates |
| `PushSDK.logout(userId?)` | Unregister and clean up |
| `isNativePushAvailable()` | Check if native push module is linked |
| `detectVendorNative()` | Detect vendor via native module |
| `registerPushNative()` | Trigger native vendor registration |
**Native module:** Requires `NativeModules.XuqmPushModule` to be linked in the host app.
---
### @xuqm/rn-update
App update check and RN plugin (bundle) hot-update. Checks for new app versions and downloads/caches RN bundles for OTA delivery.
| Export | Description |
|--------|-------------|
| `UpdateSDK.registerPlugin(meta)` | Register plugin metadata at bundle load time |
| `UpdateSDK.checkAppUpdate(bypassIgnore?)` | Check for app-level update |
| `UpdateSDK.openStore(url?, marketUrl?)` | Open app store page |
| `UpdateSDK.checkPluginUpdate(moduleId)` | Check if a plugin bundle has an update |
| `UpdateSDK.downloadPluginBundle(url)` | Download bundle source text |
| `UpdateSDK.cachePluginBundle(id, ver, md5, src)` | Cache bundle to AsyncStorage |
| `UpdateSDK.getCachedPluginBundle(id)` | Read cached bundle |
| `UpdateSDK.checkAndCachePlugin(id)` | One-step check + download + cache |
| `UpdateSDK.getRegisteredPlugins()` | List all registered plugins |
| `UpdateSDK.getAppVersionCode / getAppVersionName` | Get host app version |
**Types:** `PluginMeta`, `AppUpdateInfo`, `PluginUpdateInfo`, `CachedRnBundle`
---
### @xuqm/rn-xwebview
Enhanced WebView with JSBridge for bidirectional communication between RN and web content. Includes progress bar, inline view, and full-screen screen components.
| Export | Description |
|--------|-------------|
| `XWebViewScreen` | Full-screen WebView (React Navigation screen) |
| `XWebViewView` | Inline WebView component |
| `XWebViewProgress` | Progress bar component |
| `openXWebView(url, options?)` | Open WebView programmatically |
| `setXWebViewController(controller)` | Set global WebView controller |
| `getXWebViewConfig()` | Get current WebView config |
**Additional dependencies:** `react-native-webview`, `react-native-blob-util`, `react-native-svg`
**Additional peer dependency:** `@react-navigation/native >= 7.0.0`
---
### @xuqm/rn-license
Encrypted license file decryption and device license verification with server. Supports `XUQM-CONFIG-V1` and `XUQM-LICENSE-V1` encrypted formats.
| Export | Description |
|--------|-------------|
| `initialize(appKey, options?)` | Configure license with appKey and optional baseUrl |
| `initializeFromFile(encryptedContent)` | Decrypt and init from encrypted file |
| `checkLicense(userInfo?)` | Verify device license with server (10-min cache) |
| `getStatus()` | Returns `'ok'`, `'denied'`, or `'unknown'` |
| `getDeviceId()` | Get device ID for license check |
| `decryptLicenseFile(content)` | Decrypt `XUQM-LICENSE-V1` format |
| `decryptConfigFile(content)` | Decrypt `XUQM-CONFIG-V1` format (alias) |
**Additional peer dependency:** `react-native-quick-crypto >= 0.7.0`
---
## Development
### Prerequisites
- Node.js >= 18
- Yarn (workspaces)
- React Native development environment
### Commands
```bash
# Type-check all packages
yarn typecheck
# Type-check a single package
cd packages/im && yarn typecheck
```
### Publishing
Packages are published to the private npm registry at `https://nexus.xuqinmin.com/repository/npm-hosted/`.
```bash
# Publish a single package
cd packages/common
npm publish
# Publish all packages (from each package directory)
for pkg in common im push update xwebview license; do
cd packages/$pkg && npm publish && cd ../..
done
```
### Project layout
```
packages/<name>/
├── src/
│ └── index.ts # Public API
├── package.json
├── tsconfig.json
└── README.md
```
Each package has its own `package.json`, `tsconfig.json`, and `publishConfig` pointing to the hosted registry. The root `package.json` is a private meta-package that depends on all sub-packages.
---
## Plugin Scaffolding
The `create-plugin.mjs` script generates a new UpdateSDK plugin skeleton and auto-registers it into the host project.
### Usage
```bash
# Interactive mode
node packages/update/scripts/create-plugin.mjs
# CLI mode
node packages/update/scripts/create-plugin.mjs <moduleId> [title] [subtitle] [accentColor]
```
### What it generates
- `bundle.ts` -- Plugin entry point
- `{PascalCase}Screen.tsx` -- Screen component
- `plugin.json` -- Plugin metadata
### What it auto-registers
- `pluginCatalog.ts` -- Adds plugin to catalog
- `debugPlugins.ts` -- Adds to debug plugin list
- `package.json` -- Adds build script for the new bundle
- `metro.split.config.js` -- Adds bundle entry
- `babel.config.js` -- Adds module alias
- `tsconfig.json` -- Adds path mapping
**Module ID rules:** Lowercase alphanumeric, must be unique across all plugins.