import { createAPI, createSyncAPI, registerCanIUse, t } from './base'; import { applyNative, invokeNative } from '@jolibox/native-bridge'; import { createCommands } from '@jolibox/common'; import { innerFetch as fetch } from '../network'; import { context } from '@/common/context'; import { API_CODE, StandardResponse, StorageResponse } from '@jolibox/types'; const commands = createCommands(); const getStorage = createAPI('getLocalStorage', { paramsSchema: t.tuple(t.string()), async implement(key) { const { response } = await fetch< StorageResponse<{ key: string; value: string | null; }> >(`/api/games/user-storage/${context.mpId}`, { method: 'GET', responseType: 'json', appendHostCookie: true, query: { key } }); const { data: { code, message, data: originData } } = await response; if (code === 'SUCCESS') { return { code: code as API_CODE, message, data: originData?.value }; } try { const { data: { data, dataType } } = await applyNative('getLocalStorageAsync', { key }); const parsedData = parse(data, dataType); return { code, message: `${message}. fallback to native`, data: parsedData }; } catch (error) { return { code: 'INTERNAL_ERROR', message: '[Jolibox SDK] get local storage failed', data: null }; } } }); commands.registerCommand('StorageSDK.getItem', getStorage); registerCanIUse('storage.getItem', { version: '1.0.0', properties: { key: '1.0.0', value: '1.0.0' } }); const setStorage = createAPI('setStorage', { paramsSchema: t.tuple(t.string(), t.or(t.string(), t.boolean(), t.number())), async implement(key, value) { const gameId = context.mpId; const valueToStore = typeof value == 'string' ? value : String(value); const { response } = await fetch>(`/api/games/user-storage/${gameId}`, { method: 'POST', responseType: 'json', appendHostCookie: true, data: { key, value: valueToStore } }); const { data: { code, message } } = response; const dataType = getType(value); const data = stringify(value, dataType); // 同步备份 await applyNative('setLocalStorageAsync', { key, data, dataType }); if (code == 'SUCCESS') { return { code, message }; } else { return { code, message: `${message}. fallback to native` } as StandardResponse; } } }); commands.registerCommand('StorageSDK.setItem', setStorage); registerCanIUse('storage.setItem', { version: '1.0.0', properties: { key: '1.0.0', value: '1.0.0' } }); /** * 移除指定key */ export const removeStorage = createAPI('removeStorage', { paramsSchema: t.tuple(t.string()), async implement(key) { const gameId = context.mpId; const { response } = await fetch>(`/api/games/user-storage/${gameId}/remove`, { method: 'POST', responseType: 'json', appendHostCookie: true, data: { key } }); const { data: { code, message } } = response; await applyNative('removeLocalStorageAsync', { key }); if (code === 'SUCCESS') { return { code, message }; } else { return { code, message: '[Jolibox SDK] remove item succ' } as StandardResponse; } } }); commands.registerCommand('StorageSDK.removeItem', removeStorage); registerCanIUse('storage.removeItem', { version: '1.0.0', properties: { key: '1.0.0' } }); /** * 清理本地数据缓存 */ const clearStorage = createAPI('clearStorage', { async implement() { const gameId = context.mpId; const { response } = await fetch>(`/api/games/user-storage/${gameId}/clear`, { method: 'POST', appendHostCookie: true }); applyNative('clearLocalStorageAsync'); const { data: { code, message } } = response; if (code === 'SUCCESS') { return { code, message }; } return { code, message: `${message}.fallback to native` } as StandardResponse; } }); commands.registerCommand('StorageSDK.clear', clearStorage); registerCanIUse('storage.clear', { version: '1.0.0' }); /** * 异步获取当前storage的相关信息 */ export const getStorageInfo = createAPI('getStorageInfo', { async implement() { const { data } = await applyNative('getStorageInfoAsync'); return data; } }); registerCanIUse('getStorageInfo', { version: '1.0.0', success: { keys: '1.0.0', // string[] 本地数据缓存中的所有键名列表,如本地数据则返回空数组 currentSize: '1.0.0', // number 当前占用的空间大小,以 KB 为单位 limitSize: '1.0.0' // number 存储空间上限,以 KB 为单位,一般来说会返回 10240 } }); /** * 同步获取当前storage的相关信息 */ export const getStorageInfoSync = createSyncAPI('getStorageInfoSync', { implement() { return invokeNative('getStorageInfoSync'); } }); const DATA_TYPE = [ 'string', 'number', 'boolean', 'object', '' // 表示不支持的类型 ] as const; type DataType = typeof DATA_TYPE[number]; function getType(data: unknown): DataType { let type = Object.prototype.toString.call(data).split(' ')[1].split(']')[0].toLocaleLowerCase() as DataType; if ((type as string) === 'array') { type = 'object' as DataType; } if (DATA_TYPE.includes(type)) { return type; } return ''; } /** * 解析数据 */ function parse(str: string, type: string) { try { switch (type) { case 'string': return str; case 'object': return JSON.parse(str); case 'number': return parseFloat(str); case 'boolean': return str === 'true'; default: return ''; } } catch { return ''; } } /** * 序列化数据 */ function stringify(data: unknown, type: DataType) { try { switch (type) { case 'string': case 'number': case 'boolean': return `${data}`; case 'object': return JSON.stringify(data); default: return ''; } } catch { return ''; } } export const getGlobalStorage = createAPI('getGlobalStorage', { paramsSchema: t.tuple(t.string()), async implement(key) { try { const { data: { data, dataType } } = await applyNative('getGlobalStorageAsync', { key }); const parsedData = parse(data, dataType); return { code: 'SUCCESS', message: 'success', data: parsedData }; } catch (error) { return { code: 'INTERNAL_ERROR', message: '[Jolibox SDK] get global storage failed', data: null }; } } }); export const setGlobalStorage = createAPI('setGlobalStorage', { paramsSchema: t.tuple(t.string(), t.or(t.string(), t.boolean(), t.number(), t.array())), async implement(key, value) { try { const dataType = getType(value); const data = stringify(value, dataType); await applyNative('setGlobalStorageAsync', { key, data, dataType }); return { code: 'SUCCESS', message: 'success' }; } catch (error) { return { code: 'INTERNAL_ERROR', message: '[Jolibox SDK] set global storage failed' }; } } });