diff --git a/packages/common/src/index.ts b/packages/common/src/index.ts index 430734b..c806ed2 100644 --- a/packages/common/src/index.ts +++ b/packages/common/src/index.ts @@ -1,6 +1,7 @@ export { XuqmSDK } from './sdk' export type { XuqmInitOptions, XuqmConfig } from './config' export { getConfig, isInitialized, setUserId, getUserId } from './config' +export { awaitInitialization } from './sdk' export { apiRequest, configureHttp, _getToken, _saveToken, _clearToken } from './http' export { DEFAULT_TENANT_PLATFORM_URL, DEFAULT_IM_WS_URL } from './constants' export { getDeviceId, getDeviceInfo, detectPushVendor } from './device' diff --git a/packages/common/src/sdk.ts b/packages/common/src/sdk.ts index 76779ec..124981d 100644 --- a/packages/common/src/sdk.ts +++ b/packages/common/src/sdk.ts @@ -2,6 +2,23 @@ import { initConfigFromRemote, isInitialized, type XuqmInitOptions, setUserId as import { DEFAULT_IM_WS_URL, DEFAULT_TENANT_PLATFORM_URL } from './constants' import { configureHttp } from './http' +let _initPromise: Promise | null = null +let _initResolve: (() => void) | null = null + +function ensureInitPromise(): Promise { + if (!_initPromise) { + _initPromise = new Promise((resolve) => { _initResolve = resolve }) + } + return _initPromise +} + +function markInitialized(): void { + if (_initResolve) { + _initResolve() + _initResolve = null + } +} + export const XuqmSDK = { /** * @param options.appKey - Your application key (from the tenant platform) @@ -36,6 +53,7 @@ export const XuqmSDK = { }) if (options.debug) console.warn('[XuqmSDK] Config fetch failed, using fallback URLs', e) } + markInitialized() }, /** @@ -53,6 +71,31 @@ export const XuqmSDK = { baseUrl: DEFAULT_TENANT_PLATFORM_URL, debug: options.debug, }) + markInitialized() + }, + + /** + * Initialize from a decrypted license file object. + * Use @xuqm/rn-license's decryptLicenseFile() to decrypt the raw file content first. + */ + initializeFromLicense(file: { appKey: string; baseUrl?: string; serverUrl?: string }, options?: { debug?: boolean }): void { + if (isInitialized()) return + const serverUrl = file.serverUrl || file.baseUrl || DEFAULT_TENANT_PLATFORM_URL + initConfigFromRemote({ appKey: file.appKey, debug: options?.debug }, { + imWsUrl: DEFAULT_IM_WS_URL, + fileServiceUrl: serverUrl, + apiUrl: serverUrl, + }) + configureHttp({ baseUrl: serverUrl, debug: options?.debug }) + markInitialized() + }, + + /** + * Wait for initialization to complete. + */ + async awaitInitialization(): Promise { + if (isInitialized()) return + await ensureInitPromise() }, setUserId(userId: string | null): void { @@ -63,3 +106,8 @@ export const XuqmSDK = { return getCommonUserId() }, } + +export async function awaitInitialization(): Promise { + if (isInitialized()) return + await ensureInitPromise() +} diff --git a/packages/license/src/license.ts b/packages/license/src/license.ts index 15fb245..7c23ec4 100644 --- a/packages/license/src/license.ts +++ b/packages/license/src/license.ts @@ -1,5 +1,5 @@ import { Platform } from 'react-native' -import { getDeviceId as getCommonDeviceId, getDeviceInfo } from '@xuqm/rn-common' +import { getDeviceId as getCommonDeviceId, getDeviceInfo, awaitInitialization } from '@xuqm/rn-common' import { decryptLicenseFile } from './crypto' import * as store from './store' import type { LicenseFile, LicenseResult, LicenseStatus, LicenseUserInfo, RegisterRequest, RegisterResponse, VerifyRequest, VerifyResponse } from './models' @@ -40,7 +40,10 @@ export async function initializeFromFile(encryptedContent: string): Promise { - if (!_config) return { type: 'error', message: 'LicenseSDK not initialized' } + if (!_config) { + await awaitInitialization() + if (!_config) return { type: 'error', message: 'LicenseSDK not initialized' } + } const { appKey, baseUrl } = _config // In-memory cache check diff --git a/packages/update/src/UpdateSDK.ts b/packages/update/src/UpdateSDK.ts index c42b68c..a001644 100644 --- a/packages/update/src/UpdateSDK.ts +++ b/packages/update/src/UpdateSDK.ts @@ -2,6 +2,7 @@ import AsyncStorage from '@react-native-async-storage/async-storage' import { Linking, Platform } from 'react-native' import { apiRequest, getConfig, getUserId } from '@xuqm/rn-common' import { getAppVersionCode, getAppVersionName, _devSetAppVersion } from './NativeVersion' +import { awaitInitialization } from '@xuqm/rn-common' export interface PluginMeta { moduleId: string @@ -84,6 +85,7 @@ export const UpdateSDK = { * App version is read automatically from native code (XuqmVersionModule). */ async checkAppUpdate(): Promise { + await awaitInitialization() const config = getConfig() const currentVersionCode = getAppVersionCode() const userId = getUserId()?.trim()