2026-06-15 01:44:20 +08:00
|
|
|
import { initConfigFromRemote, isInitialized, type XuqmInitOptions, type XuqmUserInfo, setUserId as setCommonUserId, getUserId as getCommonUserId, setUserInfo as setCommonUserInfo, getUserInfo as getCommonUserInfo } from './config'
|
2026-04-29 15:46:40 +08:00
|
|
|
import { DEFAULT_IM_WS_URL, DEFAULT_TENANT_PLATFORM_URL } from './constants'
|
2026-05-08 09:27:38 +08:00
|
|
|
import { configureHttp } from './http'
|
2026-06-15 01:44:20 +08:00
|
|
|
import { decryptConfigFile } from './configCrypto'
|
2026-04-24 16:16:31 +08:00
|
|
|
|
2026-05-22 17:57:01 +08:00
|
|
|
let _initPromise: Promise<void> | null = null
|
|
|
|
|
let _initResolve: (() => void) | null = null
|
|
|
|
|
|
|
|
|
|
function ensureInitPromise(): Promise<void> {
|
|
|
|
|
if (!_initPromise) {
|
|
|
|
|
_initPromise = new Promise((resolve) => { _initResolve = resolve })
|
|
|
|
|
}
|
|
|
|
|
return _initPromise
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function markInitialized(): void {
|
|
|
|
|
if (_initResolve) {
|
|
|
|
|
_initResolve()
|
|
|
|
|
_initResolve = null
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-24 16:16:31 +08:00
|
|
|
export const XuqmSDK = {
|
|
|
|
|
/**
|
2026-04-29 15:46:40 +08:00
|
|
|
* @param options.appKey - Your application key (from the tenant platform)
|
2026-04-25 16:41:19 +08:00
|
|
|
* @param options.debug - Enable verbose logging
|
|
|
|
|
*/
|
|
|
|
|
async initialize(options: XuqmInitOptions): Promise<void> {
|
|
|
|
|
if (isInitialized()) return
|
2026-05-07 19:39:41 +08:00
|
|
|
const configUrl = `${DEFAULT_TENANT_PLATFORM_URL}/api/sdk/config?appKey=${options.appKey}`
|
2026-04-25 16:41:19 +08:00
|
|
|
try {
|
|
|
|
|
const res = await fetch(configUrl)
|
|
|
|
|
const json = await res.json()
|
|
|
|
|
const remote = json.data ?? json
|
|
|
|
|
initConfigFromRemote(options, {
|
|
|
|
|
imWsUrl: remote.imWsUrl,
|
|
|
|
|
fileServiceUrl: remote.fileServiceUrl,
|
2026-04-29 15:46:40 +08:00
|
|
|
apiUrl: remote.imApiUrl ?? DEFAULT_TENANT_PLATFORM_URL,
|
2026-04-25 16:41:19 +08:00
|
|
|
})
|
2026-05-08 09:27:38 +08:00
|
|
|
configureHttp({
|
|
|
|
|
baseUrl: remote.imApiUrl ?? DEFAULT_TENANT_PLATFORM_URL,
|
|
|
|
|
debug: options.debug,
|
|
|
|
|
})
|
2026-04-25 16:41:19 +08:00
|
|
|
} catch (e) {
|
2026-04-29 15:46:40 +08:00
|
|
|
// Fallback: construct URLs from the built-in platform endpoint
|
2026-04-25 16:41:19 +08:00
|
|
|
initConfigFromRemote(options, {
|
2026-04-29 15:46:40 +08:00
|
|
|
imWsUrl: DEFAULT_IM_WS_URL,
|
|
|
|
|
fileServiceUrl: DEFAULT_TENANT_PLATFORM_URL,
|
|
|
|
|
apiUrl: DEFAULT_TENANT_PLATFORM_URL,
|
2026-04-25 16:41:19 +08:00
|
|
|
})
|
2026-05-08 09:27:38 +08:00
|
|
|
configureHttp({
|
|
|
|
|
baseUrl: DEFAULT_TENANT_PLATFORM_URL,
|
|
|
|
|
debug: options.debug,
|
|
|
|
|
})
|
2026-04-25 16:41:19 +08:00
|
|
|
if (options.debug) console.warn('[XuqmSDK] Config fetch failed, using fallback URLs', e)
|
|
|
|
|
}
|
2026-05-22 17:57:01 +08:00
|
|
|
markInitialized()
|
2026-04-25 16:41:19 +08:00
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
2026-04-29 15:46:40 +08:00
|
|
|
* @param options.appKey - Your application key (from the tenant platform)
|
2026-04-25 16:41:19 +08:00
|
|
|
* @param options.debug - Enable verbose logging
|
2026-04-24 16:16:31 +08:00
|
|
|
*/
|
|
|
|
|
init(options: XuqmInitOptions): void {
|
|
|
|
|
if (isInitialized()) return
|
2026-04-25 16:41:19 +08:00
|
|
|
initConfigFromRemote(options, {
|
2026-04-29 15:46:40 +08:00
|
|
|
imWsUrl: DEFAULT_IM_WS_URL,
|
|
|
|
|
fileServiceUrl: DEFAULT_TENANT_PLATFORM_URL,
|
|
|
|
|
apiUrl: DEFAULT_TENANT_PLATFORM_URL,
|
2026-04-25 16:41:19 +08:00
|
|
|
})
|
2026-05-08 09:27:38 +08:00
|
|
|
configureHttp({
|
|
|
|
|
baseUrl: DEFAULT_TENANT_PLATFORM_URL,
|
|
|
|
|
debug: options.debug,
|
|
|
|
|
})
|
2026-05-22 17:57:01 +08:00
|
|
|
markInitialized()
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Initialize from a decrypted license file object.
|
|
|
|
|
*/
|
|
|
|
|
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()
|
|
|
|
|
},
|
|
|
|
|
|
2026-06-15 01:44:20 +08:00
|
|
|
/**
|
|
|
|
|
* 从加密配置文件初始化 SDK。
|
|
|
|
|
*
|
|
|
|
|
* 宿主只需传入 .xuqmconfig 文件的加密内容,SDK 自动解密并初始化。
|
|
|
|
|
* 支持 XUQM-CONFIG-V1 和 XUQM-LICENSE-V1 两种格式。
|
|
|
|
|
*
|
|
|
|
|
* @param encryptedContent 加密配置文件的完整内容
|
|
|
|
|
* @param options.debug 是否开启调试日志
|
|
|
|
|
*
|
|
|
|
|
* @example
|
|
|
|
|
* // common bundle 入口
|
|
|
|
|
* import config from './assets/app.xuqmconfig'
|
|
|
|
|
* await XuqmSDK.initWithConfigFile(config)
|
|
|
|
|
*/
|
|
|
|
|
async initWithConfigFile(encryptedContent: string, options?: { debug?: boolean }): Promise<void> {
|
|
|
|
|
if (isInitialized()) return
|
|
|
|
|
const file = await decryptConfigFile(encryptedContent)
|
|
|
|
|
this.initializeFromLicense(file, options)
|
|
|
|
|
},
|
|
|
|
|
|
2026-05-22 17:57:01 +08:00
|
|
|
/**
|
|
|
|
|
* Wait for initialization to complete.
|
|
|
|
|
*/
|
|
|
|
|
async awaitInitialization(): Promise<void> {
|
|
|
|
|
if (isInitialized()) return
|
|
|
|
|
await ensureInitPromise()
|
2026-04-24 16:16:31 +08:00
|
|
|
},
|
2026-04-28 16:55:12 +08:00
|
|
|
|
|
|
|
|
setUserId(userId: string | null): void {
|
|
|
|
|
setCommonUserId(userId)
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
getUserId(): string | null {
|
|
|
|
|
return getCommonUserId()
|
|
|
|
|
},
|
2026-06-15 01:44:20 +08:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set user info for gray release targeting and license verification.
|
|
|
|
|
* Call this after user login.
|
|
|
|
|
*/
|
|
|
|
|
setUserInfo(info: XuqmUserInfo | null): void {
|
|
|
|
|
setCommonUserInfo(info)
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
getUserInfo(): XuqmUserInfo | null {
|
|
|
|
|
return getCommonUserInfo()
|
|
|
|
|
},
|
2026-04-24 16:16:31 +08:00
|
|
|
}
|
2026-05-22 17:57:01 +08:00
|
|
|
|
|
|
|
|
export async function awaitInitialization(): Promise<void> {
|
|
|
|
|
if (isInitialized()) return
|
|
|
|
|
await ensureInitPromise()
|
|
|
|
|
}
|