@jolibox/implement 1.1.4-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +3 -0
- package/.rush/temp/package-deps_build.json +104 -0
- package/.rush/temp/shrinkwrap-deps.json +79 -0
- package/README.md +1 -0
- package/dist/common/api-factory/index.d.ts +21 -0
- package/dist/common/api-factory/validator/__tests__/validate/any.test.d.ts +1 -0
- package/dist/common/api-factory/validator/__tests__/validate/array.test.d.ts +1 -0
- package/dist/common/api-factory/validator/__tests__/validate/arraybuffer.test.d.ts +1 -0
- package/dist/common/api-factory/validator/__tests__/validate/boolean.test.d.ts +1 -0
- package/dist/common/api-factory/validator/__tests__/validate/enum.test.d.ts +1 -0
- package/dist/common/api-factory/validator/__tests__/validate/function.test.d.ts +1 -0
- package/dist/common/api-factory/validator/__tests__/validate/literal.test.d.ts +1 -0
- package/dist/common/api-factory/validator/__tests__/validate/nullish.test.d.ts +1 -0
- package/dist/common/api-factory/validator/__tests__/validate/number.test.d.ts +1 -0
- package/dist/common/api-factory/validator/__tests__/validate/object.test.d.ts +1 -0
- package/dist/common/api-factory/validator/__tests__/validate/or.test.d.ts +1 -0
- package/dist/common/api-factory/validator/__tests__/validate/record.test.d.ts +1 -0
- package/dist/common/api-factory/validator/__tests__/validate/string.test.d.ts +1 -0
- package/dist/common/api-factory/validator/__tests__/validate/symbol.test.d.ts +1 -0
- package/dist/common/api-factory/validator/__tests__/validate/tuple.test.d.ts +1 -0
- package/dist/common/api-factory/validator/__tests__/validate/type-asserts.test.d.ts +1 -0
- package/dist/common/api-factory/validator/__tests__/validate/utils.test.d.ts +1 -0
- package/dist/common/api-factory/validator/index.d.ts +29 -0
- package/dist/common/api-factory/validator/validate.d.ts +119 -0
- package/dist/common/can-i-use.d.ts +2 -0
- package/dist/common/context/index.d.ts +16 -0
- package/dist/common/context/types.d.ts +5 -0
- package/dist/common/context/url-parse.d.ts +22 -0
- package/dist/common/http/index.d.ts +13 -0
- package/dist/common/http/uuid.d.ts +2 -0
- package/dist/common/http/xua.d.ts +17 -0
- package/dist/common/report/base-tracker.d.ts +13 -0
- package/dist/common/report/create-trace.d.ts +7 -0
- package/dist/common/report/errors/error-types.d.ts +122 -0
- package/dist/common/report/errors/index.d.ts +13 -0
- package/dist/common/report/errors/report/index.d.ts +51 -0
- package/dist/common/report/errors/report/listeners.d.ts +1 -0
- package/dist/common/report/index.d.ts +3 -0
- package/dist/common/report/task-track/index.d.ts +23 -0
- package/dist/common/report/track.d.ts +3 -0
- package/dist/common/report/types.d.ts +75 -0
- package/dist/h5/ads/ads-action-detection.d.ts +6 -0
- package/dist/h5/ads/anti-cheating.d.ts +61 -0
- package/dist/h5/ads/index.d.ts +275 -0
- package/dist/h5/api/base.d.ts +13 -0
- package/dist/h5/api/get-system-info.d.ts +1 -0
- package/dist/h5/api/index.d.ts +4 -0
- package/dist/h5/api/lifecycle.d.ts +1 -0
- package/dist/h5/api/storage.d.ts +27 -0
- package/dist/h5/api/task.d.ts +1 -0
- package/dist/h5/bootstrap/index.d.ts +1 -0
- package/dist/h5/http/index.d.ts +33 -0
- package/dist/h5/http/utils/__tests__/uuid.test.d.ts +1 -0
- package/dist/h5/http/utils/__tests__/xua.test.d.ts +1 -0
- package/dist/h5/http/utils/index.d.ts +14 -0
- package/dist/h5/http/utils/session.d.ts +1 -0
- package/dist/h5/report/errors/index.d.ts +4 -0
- package/dist/h5/report/event-tracker.d.ts +8 -0
- package/dist/h5/report/index.d.ts +10 -0
- package/dist/h5/report/task-tracker.d.ts +14 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +5026 -0
- package/dist/index.native.d.ts +2 -0
- package/dist/index.native.js +3743 -0
- package/dist/native/api/base.d.ts +13 -0
- package/dist/native/api/get-system-info.d.ts +1 -0
- package/dist/native/api/index.d.ts +7 -0
- package/dist/native/api/keyboard.d.ts +3 -0
- package/dist/native/api/lifecycle.d.ts +1 -0
- package/dist/native/api/login.d.ts +1 -0
- package/dist/native/api/request.d.ts +1 -0
- package/dist/native/api/storage.d.ts +25 -0
- package/dist/native/api/task.d.ts +1 -0
- package/dist/native/bootstrap/bridge.d.ts +4 -0
- package/dist/native/bootstrap/index.d.ts +1 -0
- package/dist/native/js-bridge/const.d.ts +5 -0
- package/dist/native/js-bridge/index.d.ts +2 -0
- package/dist/native/js-bridge/invoke.d.ts +21 -0
- package/dist/native/js-bridge/js-bridge.d.ts +6 -0
- package/dist/native/js-bridge/report.d.ts +63 -0
- package/dist/native/js-bridge/subscribe.d.ts +8 -0
- package/dist/native/js-bridge/types.d.ts +14 -0
- package/dist/native/js-bridge/utils.d.ts +17 -0
- package/dist/native/js-core/index.d.ts +3 -0
- package/dist/native/js-core/jolibox-js-core.d.ts +45 -0
- package/dist/native/js-core/message-port.d.ts +12 -0
- package/dist/native/js-core/utils.d.ts +7 -0
- package/dist/native/network/create-fetch.d.ts +27 -0
- package/dist/native/network/index.d.ts +11 -0
- package/dist/native/network/report.d.ts +15 -0
- package/dist/native/network/types.d.ts +61 -0
- package/dist/native/network/utils.d.ts +9 -0
- package/dist/native/report/errors/index.d.ts +4 -0
- package/dist/native/report/index.d.ts +10 -0
- package/dist/native/report/task-tracker.d.ts +20 -0
- package/dist/utils/index.d.ts +0 -0
- package/esbuild.config.js +66 -0
- package/implement.build.log +9 -0
- package/package.json +30 -0
- package/src/common/api-factory/index.ts +188 -0
- package/src/common/api-factory/validator/__tests__/validate/any.test.ts +68 -0
- package/src/common/api-factory/validator/__tests__/validate/array.test.ts +402 -0
- package/src/common/api-factory/validator/__tests__/validate/arraybuffer.test.ts +48 -0
- package/src/common/api-factory/validator/__tests__/validate/boolean.test.ts +27 -0
- package/src/common/api-factory/validator/__tests__/validate/enum.test.ts +106 -0
- package/src/common/api-factory/validator/__tests__/validate/function.test.ts +54 -0
- package/src/common/api-factory/validator/__tests__/validate/literal.test.ts +130 -0
- package/src/common/api-factory/validator/__tests__/validate/nullish.test.ts +41 -0
- package/src/common/api-factory/validator/__tests__/validate/number.test.ts +147 -0
- package/src/common/api-factory/validator/__tests__/validate/object.test.ts +131 -0
- package/src/common/api-factory/validator/__tests__/validate/or.test.ts +96 -0
- package/src/common/api-factory/validator/__tests__/validate/record.test.ts +274 -0
- package/src/common/api-factory/validator/__tests__/validate/string.test.ts +187 -0
- package/src/common/api-factory/validator/__tests__/validate/symbol.test.ts +23 -0
- package/src/common/api-factory/validator/__tests__/validate/tuple.test.ts +86 -0
- package/src/common/api-factory/validator/__tests__/validate/type-asserts.test.ts +13 -0
- package/src/common/api-factory/validator/__tests__/validate/utils.test.ts +44 -0
- package/src/common/api-factory/validator/index.ts +107 -0
- package/src/common/api-factory/validator/validate.ts +639 -0
- package/src/common/can-i-use.ts +19 -0
- package/src/common/context/index.ts +91 -0
- package/src/common/context/types.ts +5 -0
- package/src/common/context/url-parse.ts +63 -0
- package/src/common/http/index.ts +29 -0
- package/src/common/http/uuid.ts +11 -0
- package/src/common/http/xua.ts +79 -0
- package/src/common/report/base-tracker.ts +134 -0
- package/src/common/report/create-trace.ts +17 -0
- package/src/common/report/errors/error-types.ts +206 -0
- package/src/common/report/errors/index.ts +20 -0
- package/src/common/report/errors/report/index.ts +63 -0
- package/src/common/report/errors/report/listeners.ts +80 -0
- package/src/common/report/index.ts +3 -0
- package/src/common/report/task-track/index.ts +97 -0
- package/src/common/report/track.ts +49 -0
- package/src/common/report/types.ts +90 -0
- package/src/h5/ads/ads-action-detection.ts +31 -0
- package/src/h5/ads/anti-cheating.ts +244 -0
- package/src/h5/ads/index.ts +641 -0
- package/src/h5/api/base.ts +9 -0
- package/src/h5/api/get-system-info.ts +55 -0
- package/src/h5/api/index.ts +4 -0
- package/src/h5/api/lifecycle.ts +110 -0
- package/src/h5/api/storage.ts +173 -0
- package/src/h5/api/task.ts +197 -0
- package/src/h5/bootstrap/index.ts +16 -0
- package/src/h5/http/index.ts +189 -0
- package/src/h5/http/utils/__tests__/uuid.test.ts +16 -0
- package/src/h5/http/utils/__tests__/xua.test.ts +27 -0
- package/src/h5/http/utils/index.ts +19 -0
- package/src/h5/http/utils/session.ts +10 -0
- package/src/h5/report/errors/index.ts +40 -0
- package/src/h5/report/event-tracker.ts +40 -0
- package/src/h5/report/index.ts +56 -0
- package/src/h5/report/task-tracker.ts +35 -0
- package/src/index.native.ts +7 -0
- package/src/index.ts +9 -0
- package/src/native/api/base.ts +8 -0
- package/src/native/api/get-system-info.ts +41 -0
- package/src/native/api/index.ts +7 -0
- package/src/native/api/keyboard.ts +75 -0
- package/src/native/api/lifecycle.ts +76 -0
- package/src/native/api/login.ts +71 -0
- package/src/native/api/request.ts +154 -0
- package/src/native/api/storage.ts +287 -0
- package/src/native/api/task.ts +267 -0
- package/src/native/bootstrap/bridge.ts +59 -0
- package/src/native/bootstrap/index.ts +58 -0
- package/src/native/js-bridge/const.ts +11 -0
- package/src/native/js-bridge/index.ts +2 -0
- package/src/native/js-bridge/invoke.ts +210 -0
- package/src/native/js-bridge/js-bridge.ts +23 -0
- package/src/native/js-bridge/report.ts +311 -0
- package/src/native/js-bridge/subscribe.ts +50 -0
- package/src/native/js-bridge/types.ts +26 -0
- package/src/native/js-bridge/utils.ts +116 -0
- package/src/native/js-core/index.ts +4 -0
- package/src/native/js-core/jolibox-js-core.ts +188 -0
- package/src/native/js-core/message-port.ts +52 -0
- package/src/native/js-core/utils.ts +9 -0
- package/src/native/network/create-fetch.ts +237 -0
- package/src/native/network/index.ts +15 -0
- package/src/native/network/report.ts +58 -0
- package/src/native/network/types.ts +77 -0
- package/src/native/network/utils.ts +90 -0
- package/src/native/report/errors/index.ts +27 -0
- package/src/native/report/index.ts +51 -0
- package/src/native/report/task-tracker.ts +64 -0
- package/src/native/types/global.d.ts +26 -0
- package/src/native/types/native-method-map.d.ts +282 -0
- package/src/native/types/native-method.d.ts +30 -0
- package/src/utils/index.ts +0 -0
- package/tsconfig.json +18 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { BaseError, createCommands, EventEmitter, hostEmitter, wrapUserFunction } from '@jolibox/common';
|
|
2
|
+
import { createAPI, createSyncAPI, registerCanIUse, t } from './base';
|
|
3
|
+
import { reportError } from '@/common/report/errors/report';
|
|
4
|
+
import { h5TaskEmitter } from '../report';
|
|
5
|
+
|
|
6
|
+
const EXIT_GAME = 'exitGame';
|
|
7
|
+
const ON_GAME_SHOW = 'onGameShow';
|
|
8
|
+
const ON_GAME_HIDE = 'onGameHide';
|
|
9
|
+
const ON_READY = 'onReady';
|
|
10
|
+
|
|
11
|
+
const commands = createCommands();
|
|
12
|
+
|
|
13
|
+
const safeCallbackWrapper = wrapUserFunction(reportError as (err: Error | BaseError) => void);
|
|
14
|
+
const exitGame = createAPI(EXIT_GAME, {
|
|
15
|
+
async implement(onBeforeExit: () => void) {
|
|
16
|
+
const safeCallback = safeCallbackWrapper(onBeforeExit);
|
|
17
|
+
// 集中上报
|
|
18
|
+
safeCallback.call(this);
|
|
19
|
+
|
|
20
|
+
//exit
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
let isPageVisible = true;
|
|
25
|
+
let isPageFocused = true;
|
|
26
|
+
let lastEventTime = 0;
|
|
27
|
+
|
|
28
|
+
const visibleEmitter = h5TaskEmitter;
|
|
29
|
+
|
|
30
|
+
// 防止交叉触发
|
|
31
|
+
function handleVisibilityChange() {
|
|
32
|
+
const currentTime = Date.now();
|
|
33
|
+
if (currentTime - lastEventTime < 100) return; // 忽略100ms内的重复触发
|
|
34
|
+
lastEventTime = currentTime;
|
|
35
|
+
|
|
36
|
+
const currentState = document.visibilityState === 'visible';
|
|
37
|
+
if (currentState !== isPageVisible) {
|
|
38
|
+
isPageVisible = currentState;
|
|
39
|
+
visibleEmitter.emit('visible', isPageVisible);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function handleFocusBlur(eventType: string) {
|
|
44
|
+
const currentTime = Date.now();
|
|
45
|
+
if (currentTime - lastEventTime < 100) return; // 忽略100ms内的重复触发
|
|
46
|
+
lastEventTime = currentTime;
|
|
47
|
+
|
|
48
|
+
if (eventType === 'focus' && !isPageFocused) {
|
|
49
|
+
isPageFocused = true;
|
|
50
|
+
} else if (eventType === 'blur' && isPageFocused) {
|
|
51
|
+
isPageFocused = false;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
visibleEmitter.emit('visible', isPageFocused);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
document.addEventListener('visibilitychange', handleVisibilityChange);
|
|
58
|
+
window.addEventListener('focus', () => handleFocusBlur('focus'));
|
|
59
|
+
window.addEventListener('blur', () => handleFocusBlur('blur'));
|
|
60
|
+
|
|
61
|
+
const onGameShow = createSyncAPI(ON_GAME_SHOW, {
|
|
62
|
+
paramsSchema: t.tuple(t.function()),
|
|
63
|
+
implement(callback) {
|
|
64
|
+
const safeCallback = safeCallbackWrapper(callback);
|
|
65
|
+
visibleEmitter.on('visible', (visible) => {
|
|
66
|
+
visible && safeCallback();
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
const onGameHide = createSyncAPI(ON_GAME_HIDE, {
|
|
72
|
+
paramsSchema: t.tuple(t.function()),
|
|
73
|
+
implement(callback) {
|
|
74
|
+
const safeCallback = safeCallbackWrapper(callback);
|
|
75
|
+
visibleEmitter.on('visible', (visible) => {
|
|
76
|
+
!visible && safeCallback();
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
const onReadyHandler = createSyncAPI(ON_READY, {
|
|
82
|
+
paramsSchema: t.tuple(t.function()),
|
|
83
|
+
implement(callback) {
|
|
84
|
+
const safeCallback = safeCallbackWrapper(callback);
|
|
85
|
+
hostEmitter.on('LifecycleEvent.onReady', (info) => {
|
|
86
|
+
safeCallback(info);
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
commands.registerCommand('LifecycleSDK.exit', exitGame);
|
|
92
|
+
commands.registerCommand('LifecycleSDK.onReady', onReadyHandler);
|
|
93
|
+
commands.registerCommand('LifecycleSDK.onJoliboxShow', onGameShow);
|
|
94
|
+
commands.registerCommand('LifecycleSDK.onJoliboxHide', onGameHide);
|
|
95
|
+
|
|
96
|
+
registerCanIUse('lifeCycle.exitGame', {
|
|
97
|
+
version: '1.0.0' // mock
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
registerCanIUse('lifeCycle.onReady', {
|
|
101
|
+
version: '1.0.0' // mock
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
registerCanIUse('lifeCycle.onGameShow', {
|
|
105
|
+
version: '1.0.0' // mock
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
registerCanIUse('lifeCycle.onGameHide', {
|
|
109
|
+
version: '1.0.0' // mock
|
|
110
|
+
});
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { createAPI, t, registerCanIUse } from './base';
|
|
2
|
+
import { createCommands, isBoolean, isNumber, isString } from '@jolibox/common';
|
|
3
|
+
import JoliboxHttpClient from '@/h5/http';
|
|
4
|
+
import { context } from '@/common/context';
|
|
5
|
+
import { API_CODE, StorageResponse } from '@jolibox/types';
|
|
6
|
+
import localForage from 'localforage';
|
|
7
|
+
|
|
8
|
+
const commands = createCommands();
|
|
9
|
+
|
|
10
|
+
export class JoliboxCloudStorage {
|
|
11
|
+
private gameId: string;
|
|
12
|
+
private httpClient: JoliboxHttpClient;
|
|
13
|
+
private gameStore: LocalForage;
|
|
14
|
+
constructor() {
|
|
15
|
+
this.gameId = this.getGameId();
|
|
16
|
+
this.httpClient = new JoliboxHttpClient({
|
|
17
|
+
baseUrl: context.testMode ? 'https://stg-api.jolibox.com' : 'https://api.jolibox.com'
|
|
18
|
+
});
|
|
19
|
+
//没有game的情况使用全局空间
|
|
20
|
+
this.gameStore = localForage.createInstance({
|
|
21
|
+
name: this.gameId.length ? this.gameId : 'default'
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Cloud storage getItem api
|
|
26
|
+
*/
|
|
27
|
+
private getGameId = () => context.game_id;
|
|
28
|
+
/**
|
|
29
|
+
*
|
|
30
|
+
* @param key getItem key
|
|
31
|
+
*/
|
|
32
|
+
getItem = async (key: string): Promise<StorageResponse<string | null>> => {
|
|
33
|
+
const {
|
|
34
|
+
code,
|
|
35
|
+
data: originData,
|
|
36
|
+
message
|
|
37
|
+
} = await this.httpClient.get<
|
|
38
|
+
StorageResponse<{
|
|
39
|
+
key: string;
|
|
40
|
+
value: string | null;
|
|
41
|
+
}>
|
|
42
|
+
>(`/api/games/user-storage/${this.gameId}`, {
|
|
43
|
+
query: {
|
|
44
|
+
key
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
let data = originData?.value;
|
|
48
|
+
let fallbackmsg = message;
|
|
49
|
+
if (code !== 'SUCCESS') {
|
|
50
|
+
// Only when data cannot be retrieved from the cloud should it be read locally.
|
|
51
|
+
data = await this.gameStore.getItem<string>(key);
|
|
52
|
+
console.info('[SDK] cloud storage getItem failed, read from localstorage', data);
|
|
53
|
+
fallbackmsg += 'fallback to localstorage';
|
|
54
|
+
}
|
|
55
|
+
const res = {
|
|
56
|
+
code,
|
|
57
|
+
message: fallbackmsg,
|
|
58
|
+
data: data && data !== 'undefined' ? data : null
|
|
59
|
+
};
|
|
60
|
+
return res;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Cloud storage setItem api
|
|
65
|
+
* @param progress - The progress of the loading, should be an integer between 0 and 100
|
|
66
|
+
*/
|
|
67
|
+
setItem = async (key: string, value: string | boolean | number): Promise<StorageResponse<void>> => {
|
|
68
|
+
const valueToStore = typeof value == 'string' ? value : String(value);
|
|
69
|
+
//Regardless of whether the cloud operation is successful, corresponding changes should be made locally.
|
|
70
|
+
const { code, message } = await this.httpClient.post(`/api/games/user-storage/${this.gameId}`, {
|
|
71
|
+
data: {
|
|
72
|
+
key,
|
|
73
|
+
value: valueToStore
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
await this.gameStore.setItem(key, valueToStore);
|
|
77
|
+
return {
|
|
78
|
+
code,
|
|
79
|
+
message
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
removeItem = async (key: string): Promise<StorageResponse<void>> => {
|
|
84
|
+
await this.gameStore.removeItem(key);
|
|
85
|
+
const { code, message } = await this.httpClient.post(`/api/games/user-storage/${this.gameId}/remove`, {
|
|
86
|
+
data: {
|
|
87
|
+
key
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
return {
|
|
91
|
+
code,
|
|
92
|
+
message
|
|
93
|
+
};
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
clear = async (): Promise<StorageResponse<void>> => {
|
|
97
|
+
await this.gameStore.clear();
|
|
98
|
+
const { code, message } = await this.httpClient.post(`/api/games/user-storage/${this.gameId}/clear`, {});
|
|
99
|
+
return {
|
|
100
|
+
code,
|
|
101
|
+
message
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const storageImpl = new JoliboxCloudStorage();
|
|
107
|
+
const getStorage = createAPI('getLocalStorage', {
|
|
108
|
+
paramsSchema: t.tuple(t.string()),
|
|
109
|
+
async implement(key) {
|
|
110
|
+
return await storageImpl.getItem(key);
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
commands.registerCommand('StorageSDK.getItem', getStorage);
|
|
115
|
+
|
|
116
|
+
registerCanIUse('storage.getItem', {
|
|
117
|
+
version: '1.0.0',
|
|
118
|
+
properties: {
|
|
119
|
+
key: '1.0.0',
|
|
120
|
+
value: '1.0.0'
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
const setStorage = createAPI('setStorage', {
|
|
125
|
+
paramsSchema: t.tuple(t.string(), t.or(t.string(), t.boolean(), t.number())),
|
|
126
|
+
async implement(key, value) {
|
|
127
|
+
return await storageImpl.setItem(key, value);
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
commands.registerCommand('StorageSDK.setItem', setStorage);
|
|
132
|
+
|
|
133
|
+
registerCanIUse('storage.setItem', {
|
|
134
|
+
version: '1.0.0',
|
|
135
|
+
properties: {
|
|
136
|
+
key: '1.0.0',
|
|
137
|
+
value: '1.0.0'
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* 移除指定key
|
|
143
|
+
*/
|
|
144
|
+
export const removeStorage = createAPI('removeStorage', {
|
|
145
|
+
paramsSchema: t.tuple(t.string()),
|
|
146
|
+
async implement(key) {
|
|
147
|
+
return await storageImpl.removeItem(key);
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
commands.registerCommand('StorageSDK.removeItem', removeStorage);
|
|
152
|
+
|
|
153
|
+
registerCanIUse('storage.removeItem', {
|
|
154
|
+
version: '1.0.0',
|
|
155
|
+
properties: {
|
|
156
|
+
key: '1.0.0'
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* 清理本地数据缓存
|
|
162
|
+
*/
|
|
163
|
+
const clearStorage = createAPI('clearStorage', {
|
|
164
|
+
async implement() {
|
|
165
|
+
return await storageImpl.clear();
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
commands.registerCommand('StorageSDK.clear', clearStorage);
|
|
170
|
+
|
|
171
|
+
registerCanIUse('storage.clear', {
|
|
172
|
+
version: '1.0.0'
|
|
173
|
+
});
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { createCommands, logger } from '@jolibox/common';
|
|
2
|
+
|
|
3
|
+
import { createAPI, registerCanIUse, t } from './base';
|
|
4
|
+
import { taskTracker } from '../report';
|
|
5
|
+
|
|
6
|
+
const commands = createCommands();
|
|
7
|
+
|
|
8
|
+
const onLevelFinished = createAPI('levelFinished', {
|
|
9
|
+
paramsSchema: t.tuple(
|
|
10
|
+
t.string(),
|
|
11
|
+
t.object({
|
|
12
|
+
result: t.boolean(),
|
|
13
|
+
duration: t.number()
|
|
14
|
+
})
|
|
15
|
+
),
|
|
16
|
+
implement: async (levelId, parmas) => {
|
|
17
|
+
const { result, duration } = parmas;
|
|
18
|
+
logger.info(`onLevelFinished`, result, duration);
|
|
19
|
+
return taskTracker.reporter({
|
|
20
|
+
event: 'COMPLETE_QUEST'
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const onTaskFinished = createAPI('taskFinished', {
|
|
26
|
+
paramsSchema: t.tuple(
|
|
27
|
+
t.string(),
|
|
28
|
+
t.object({
|
|
29
|
+
duration: t.number()
|
|
30
|
+
})
|
|
31
|
+
),
|
|
32
|
+
implement: async (taskId, params) => {
|
|
33
|
+
const { duration } = params;
|
|
34
|
+
logger.info(`onTaskFinished`, duration);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const onLevelUpgrade = createAPI('levelUpgrade', {
|
|
39
|
+
paramsSchema: t.tuple(t.string(), t.string()),
|
|
40
|
+
implement: async (levelId, name) => {
|
|
41
|
+
return await taskTracker.reporter({
|
|
42
|
+
event: 'COMPLETE_QUEST'
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const onHistoryUserLevel = createAPI('onHistoryUserLevel', {
|
|
48
|
+
paramsSchema: t.tuple(t.number()),
|
|
49
|
+
implement: async (level) => {
|
|
50
|
+
logger.info('onHistoryUserLevel', level);
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const onHistoryUserScore = createAPI('onHistoryUserScore', {
|
|
55
|
+
paramsSchema: t.tuple(t.number()),
|
|
56
|
+
implement: async (score) => {
|
|
57
|
+
logger.info('onHistoryUserScore', score);
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
const onTaskEvent = createAPI('taskEvent', {
|
|
62
|
+
paramsSchema: t.tuple(
|
|
63
|
+
t.string(),
|
|
64
|
+
t.object({
|
|
65
|
+
tools: t
|
|
66
|
+
.array(
|
|
67
|
+
t.object({
|
|
68
|
+
id: t.string(),
|
|
69
|
+
name: t.string(),
|
|
70
|
+
count: t.number(),
|
|
71
|
+
description: t.string().optional(),
|
|
72
|
+
price: t
|
|
73
|
+
.object({
|
|
74
|
+
amount: t.number(),
|
|
75
|
+
unit: t.string()
|
|
76
|
+
})
|
|
77
|
+
.optional()
|
|
78
|
+
})
|
|
79
|
+
)
|
|
80
|
+
.optional(),
|
|
81
|
+
awards: t
|
|
82
|
+
.array(
|
|
83
|
+
t.object({
|
|
84
|
+
id: t.string(),
|
|
85
|
+
name: t.string()
|
|
86
|
+
})
|
|
87
|
+
)
|
|
88
|
+
.optional()
|
|
89
|
+
})
|
|
90
|
+
),
|
|
91
|
+
implement: async (taskId, params) => {
|
|
92
|
+
if (params.tools?.length) {
|
|
93
|
+
return await taskTracker.reporter({
|
|
94
|
+
event: 'USE_GAME_ITEM'
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
const onTaskPayment = createAPI('taskPayment', {
|
|
101
|
+
paramsSchema: t.tuple(
|
|
102
|
+
t.string(),
|
|
103
|
+
t.object({
|
|
104
|
+
id: t.string(),
|
|
105
|
+
amount: t.number(),
|
|
106
|
+
unit: t.string()
|
|
107
|
+
})
|
|
108
|
+
),
|
|
109
|
+
implement: async () => {
|
|
110
|
+
return await taskTracker.reporter({
|
|
111
|
+
event: 'IN_GAME_PURCHASES'
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
commands.registerCommand('TaskTrackerSDK.levelFinished', onLevelFinished);
|
|
117
|
+
commands.registerCommand('TaskTrackerSDK.taskFinished', onTaskFinished);
|
|
118
|
+
commands.registerCommand('TaskTrackerSDK.levelUpgrade', onLevelUpgrade);
|
|
119
|
+
commands.registerCommand('TaskTrackerSDK.historyUserLevel', onHistoryUserLevel);
|
|
120
|
+
commands.registerCommand('TaskTrackerSDK.historyUserScore', onHistoryUserScore);
|
|
121
|
+
commands.registerCommand('TaskTrackerSDK.taskEvent', onTaskEvent);
|
|
122
|
+
commands.registerCommand('TaskTrackerSDK.taskPayment', onTaskPayment);
|
|
123
|
+
|
|
124
|
+
registerCanIUse('TaskTrackerSDK.onLevelFinished', {
|
|
125
|
+
version: '1.0.0',
|
|
126
|
+
properties: {
|
|
127
|
+
levelId: '1.0.0',
|
|
128
|
+
params: {
|
|
129
|
+
result: '1.0.0',
|
|
130
|
+
duration: '1.0.0'
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
registerCanIUse('TaskTrackerSDK.onTaskFinished', {
|
|
136
|
+
version: '1.0.0',
|
|
137
|
+
properties: {
|
|
138
|
+
taskId: '1.0.0',
|
|
139
|
+
duration: '1.0.0'
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
registerCanIUse('TaskTrackerSDK.onLevelUpgrade', {
|
|
144
|
+
version: '1.0.0',
|
|
145
|
+
properties: {
|
|
146
|
+
levelId: '1.0.0',
|
|
147
|
+
name: '1.0.0'
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
registerCanIUse('TaskTrackerSDK.onHistoryUserLevel', {
|
|
152
|
+
version: '1.0.0',
|
|
153
|
+
properties: {
|
|
154
|
+
level: '1.0.0'
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
registerCanIUse('TaskTrackerSDK.onHistoryUserScore', {
|
|
159
|
+
version: '1.0.0',
|
|
160
|
+
properties: {
|
|
161
|
+
score: '1.0.0'
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
registerCanIUse('TaskTrackerSDK.onTaskEvent', {
|
|
166
|
+
version: '1.0.0',
|
|
167
|
+
properties: {
|
|
168
|
+
taskId: '1.0.0',
|
|
169
|
+
params: {
|
|
170
|
+
tools: {
|
|
171
|
+
id: '1.0.0',
|
|
172
|
+
name: '1.0.0',
|
|
173
|
+
count: '1.0.0',
|
|
174
|
+
description: '1.0.0',
|
|
175
|
+
price: {
|
|
176
|
+
amount: '1.0.0',
|
|
177
|
+
unit: '1.0.0'
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
awards: {
|
|
181
|
+
id: '1.0.0',
|
|
182
|
+
name: '1.0.0'
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
registerCanIUse('TaskTrackerSDK.onTaskPayment', {
|
|
189
|
+
version: '1.0.0',
|
|
190
|
+
properties: {
|
|
191
|
+
taskId: '1.0.0',
|
|
192
|
+
params: {
|
|
193
|
+
amount: '1.0.0',
|
|
194
|
+
unit: '1.0.0'
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { hostEmitter } from '@jolibox/common';
|
|
2
|
+
import { taskTracker } from '../report';
|
|
3
|
+
|
|
4
|
+
function addDomContentLoaded() {
|
|
5
|
+
hostEmitter.on('onDocumentReady', (startTime: number) => {
|
|
6
|
+
hostEmitter.emit('LifecycleEvent.onReady', {
|
|
7
|
+
isLogin: false
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
taskTracker.start(Date.now() - startTime);
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function config(): void {
|
|
15
|
+
addDomContentLoaded();
|
|
16
|
+
}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { IHttpClient } from '@/common/http';
|
|
2
|
+
import { xUserAgent } from '../../common/http/xua';
|
|
3
|
+
import { context } from '@/common/context';
|
|
4
|
+
|
|
5
|
+
declare global {
|
|
6
|
+
interface Window {
|
|
7
|
+
JoliboxHttpClient: typeof JoliboxHttpClient;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface IHttpClientInitParams {
|
|
12
|
+
baseUrl?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const timeoutFn = (ms: number) => {
|
|
16
|
+
const ctrl = new AbortController();
|
|
17
|
+
setTimeout(() => ctrl.abort(), ms);
|
|
18
|
+
return ctrl.signal;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
(AbortSignal as any).timeout ??= timeoutFn;
|
|
22
|
+
|
|
23
|
+
export class JoliboxHttpClient implements IHttpClient {
|
|
24
|
+
private baseUrl: string;
|
|
25
|
+
private xua = xUserAgent();
|
|
26
|
+
|
|
27
|
+
private getJoliSource = () => {
|
|
28
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
29
|
+
return urlParams.get('joliSource') ?? null;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
// private getApiBaseURL = () => {
|
|
33
|
+
// const urlParams = new URLSearchParams(window.location.search);
|
|
34
|
+
// return urlParams.get('apiBaseURL') ?? null;
|
|
35
|
+
// };
|
|
36
|
+
|
|
37
|
+
constructor(config?: IHttpClientInitParams) {
|
|
38
|
+
const defaultUrl = context.testMode ? 'https://stg-api.jolibox.com' : 'https://api.jolibox.com';
|
|
39
|
+
this.baseUrl = config?.baseUrl ?? defaultUrl;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async get<T>(
|
|
43
|
+
path: string,
|
|
44
|
+
{
|
|
45
|
+
query,
|
|
46
|
+
headers,
|
|
47
|
+
timeout
|
|
48
|
+
}: {
|
|
49
|
+
query?: Record<string, string>;
|
|
50
|
+
headers?: Record<string, string>;
|
|
51
|
+
timeout?: number;
|
|
52
|
+
}
|
|
53
|
+
) {
|
|
54
|
+
const searchParams = new URLSearchParams(query);
|
|
55
|
+
const search = searchParams.toString();
|
|
56
|
+
const url = `${this.baseUrl}${path}${search ? `?${search}` : ''}`;
|
|
57
|
+
const xua = this.xua;
|
|
58
|
+
const joliSource = this.getJoliSource();
|
|
59
|
+
headers = Object.assign(
|
|
60
|
+
{},
|
|
61
|
+
headers,
|
|
62
|
+
xua ? { 'x-user-agent': xua } : {},
|
|
63
|
+
joliSource ? { 'x-joli-source': joliSource } : {}
|
|
64
|
+
);
|
|
65
|
+
const response = await fetch(url, {
|
|
66
|
+
method: 'GET',
|
|
67
|
+
headers,
|
|
68
|
+
signal: timeoutFn(timeout ?? 30000)
|
|
69
|
+
});
|
|
70
|
+
return (await response.json()) as T;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async post<T = any>(
|
|
74
|
+
path: string,
|
|
75
|
+
{
|
|
76
|
+
data,
|
|
77
|
+
query,
|
|
78
|
+
headers,
|
|
79
|
+
timeout
|
|
80
|
+
}: {
|
|
81
|
+
data?: any;
|
|
82
|
+
query?: Record<string, string>;
|
|
83
|
+
headers?: Record<string, string>;
|
|
84
|
+
timeout?: number;
|
|
85
|
+
}
|
|
86
|
+
) {
|
|
87
|
+
const searchParams = new URLSearchParams(query);
|
|
88
|
+
const search = searchParams.toString();
|
|
89
|
+
const url = `${this.baseUrl}${path}${search ? `?${search}` : ''}`;
|
|
90
|
+
const xua = this.xua;
|
|
91
|
+
const joliSource = this.getJoliSource();
|
|
92
|
+
headers = Object.assign(
|
|
93
|
+
{},
|
|
94
|
+
headers,
|
|
95
|
+
{ 'Content-Type': 'application/json' },
|
|
96
|
+
xua ? { 'x-user-agent': xua } : {},
|
|
97
|
+
joliSource ? { 'x-joli-source': joliSource } : {}
|
|
98
|
+
);
|
|
99
|
+
const response = await fetch(url, {
|
|
100
|
+
method: 'POST',
|
|
101
|
+
headers,
|
|
102
|
+
body: JSON.stringify(data),
|
|
103
|
+
signal: timeoutFn(timeout ?? 30000)
|
|
104
|
+
});
|
|
105
|
+
const responseContentType = response.headers.get('content-type');
|
|
106
|
+
|
|
107
|
+
// return blob
|
|
108
|
+
if (responseContentType?.includes('application/octet-stream')) {
|
|
109
|
+
try {
|
|
110
|
+
return response.blob() as unknown as T;
|
|
111
|
+
} catch (e) {
|
|
112
|
+
return (await response.arrayBuffer()) as unknown as T;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// return form data
|
|
117
|
+
if (
|
|
118
|
+
responseContentType?.includes('multipart/form-data') ||
|
|
119
|
+
responseContentType?.includes('application/x-www-form-urlencoded')
|
|
120
|
+
) {
|
|
121
|
+
try {
|
|
122
|
+
return response.formData() as unknown as T;
|
|
123
|
+
} catch (e) {
|
|
124
|
+
return (await response.text()) as unknown as T;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// return json
|
|
129
|
+
if (responseContentType?.includes('application/json')) {
|
|
130
|
+
try {
|
|
131
|
+
return (await response.json()) as T;
|
|
132
|
+
} catch (e) {
|
|
133
|
+
return (await response.text()) as unknown as T;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// return text
|
|
138
|
+
return response as unknown as T;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
async put<T>(
|
|
142
|
+
path: string,
|
|
143
|
+
{
|
|
144
|
+
data,
|
|
145
|
+
query,
|
|
146
|
+
headers
|
|
147
|
+
}: {
|
|
148
|
+
data?: any;
|
|
149
|
+
query?: Record<string, string>;
|
|
150
|
+
headers?: Record<string, string>;
|
|
151
|
+
timeout?: number;
|
|
152
|
+
}
|
|
153
|
+
) {
|
|
154
|
+
try {
|
|
155
|
+
const searchParams = new URLSearchParams(query);
|
|
156
|
+
const search = searchParams.toString();
|
|
157
|
+
const url = `${this.baseUrl}${path}${search ? `?${search}` : ''}`;
|
|
158
|
+
const xua = this.xua;
|
|
159
|
+
const joliSource = this.getJoliSource();
|
|
160
|
+
headers = Object.assign(
|
|
161
|
+
{},
|
|
162
|
+
headers,
|
|
163
|
+
{ 'Content-Type': 'application/json' },
|
|
164
|
+
xua ? { 'x-user-agent': xua } : {},
|
|
165
|
+
joliSource ? { 'x-joli-source': joliSource } : {}
|
|
166
|
+
);
|
|
167
|
+
const response = await fetch(url, {
|
|
168
|
+
method: 'PUT',
|
|
169
|
+
headers,
|
|
170
|
+
body: JSON.stringify(data ?? {}) // 将数据转换为 JSON 字符串
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
// 检查响应状态
|
|
174
|
+
if (!response.ok) {
|
|
175
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const result = (await response.json()) as T;
|
|
179
|
+
return result;
|
|
180
|
+
} catch (error) {
|
|
181
|
+
console.error('Error:', error);
|
|
182
|
+
throw error;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
window.JoliboxHttpClient = JoliboxHttpClient;
|
|
188
|
+
|
|
189
|
+
export default JoliboxHttpClient;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// import { expect, test } from "vitest";
|
|
2
|
+
import { isValidUUIDV4, uuidv4 } from '../../../../common/http/uuid';
|
|
3
|
+
|
|
4
|
+
describe('uuid', () => {
|
|
5
|
+
it('test uuid', () => {
|
|
6
|
+
const uuid = uuidv4();
|
|
7
|
+
expect(uuid.length).toBe(36);
|
|
8
|
+
expect(isValidUUIDV4(uuid)).toBe(true);
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it('isValidUUIDV4', () => {
|
|
12
|
+
const randomUUIDV4 = '5b1e0b7b-3b3b-4b4b-8b8b-9b9b0b1b2b3b';
|
|
13
|
+
expect(isValidUUIDV4(randomUUIDV4)).toBe(true);
|
|
14
|
+
expect(isValidUUIDV4('')).toBe(false);
|
|
15
|
+
});
|
|
16
|
+
});
|