@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.
Files changed (193) hide show
  1. package/.eslintrc.js +3 -0
  2. package/.rush/temp/package-deps_build.json +104 -0
  3. package/.rush/temp/shrinkwrap-deps.json +79 -0
  4. package/README.md +1 -0
  5. package/dist/common/api-factory/index.d.ts +21 -0
  6. package/dist/common/api-factory/validator/__tests__/validate/any.test.d.ts +1 -0
  7. package/dist/common/api-factory/validator/__tests__/validate/array.test.d.ts +1 -0
  8. package/dist/common/api-factory/validator/__tests__/validate/arraybuffer.test.d.ts +1 -0
  9. package/dist/common/api-factory/validator/__tests__/validate/boolean.test.d.ts +1 -0
  10. package/dist/common/api-factory/validator/__tests__/validate/enum.test.d.ts +1 -0
  11. package/dist/common/api-factory/validator/__tests__/validate/function.test.d.ts +1 -0
  12. package/dist/common/api-factory/validator/__tests__/validate/literal.test.d.ts +1 -0
  13. package/dist/common/api-factory/validator/__tests__/validate/nullish.test.d.ts +1 -0
  14. package/dist/common/api-factory/validator/__tests__/validate/number.test.d.ts +1 -0
  15. package/dist/common/api-factory/validator/__tests__/validate/object.test.d.ts +1 -0
  16. package/dist/common/api-factory/validator/__tests__/validate/or.test.d.ts +1 -0
  17. package/dist/common/api-factory/validator/__tests__/validate/record.test.d.ts +1 -0
  18. package/dist/common/api-factory/validator/__tests__/validate/string.test.d.ts +1 -0
  19. package/dist/common/api-factory/validator/__tests__/validate/symbol.test.d.ts +1 -0
  20. package/dist/common/api-factory/validator/__tests__/validate/tuple.test.d.ts +1 -0
  21. package/dist/common/api-factory/validator/__tests__/validate/type-asserts.test.d.ts +1 -0
  22. package/dist/common/api-factory/validator/__tests__/validate/utils.test.d.ts +1 -0
  23. package/dist/common/api-factory/validator/index.d.ts +29 -0
  24. package/dist/common/api-factory/validator/validate.d.ts +119 -0
  25. package/dist/common/can-i-use.d.ts +2 -0
  26. package/dist/common/context/index.d.ts +16 -0
  27. package/dist/common/context/types.d.ts +5 -0
  28. package/dist/common/context/url-parse.d.ts +22 -0
  29. package/dist/common/http/index.d.ts +13 -0
  30. package/dist/common/http/uuid.d.ts +2 -0
  31. package/dist/common/http/xua.d.ts +17 -0
  32. package/dist/common/report/base-tracker.d.ts +13 -0
  33. package/dist/common/report/create-trace.d.ts +7 -0
  34. package/dist/common/report/errors/error-types.d.ts +122 -0
  35. package/dist/common/report/errors/index.d.ts +13 -0
  36. package/dist/common/report/errors/report/index.d.ts +51 -0
  37. package/dist/common/report/errors/report/listeners.d.ts +1 -0
  38. package/dist/common/report/index.d.ts +3 -0
  39. package/dist/common/report/task-track/index.d.ts +23 -0
  40. package/dist/common/report/track.d.ts +3 -0
  41. package/dist/common/report/types.d.ts +75 -0
  42. package/dist/h5/ads/ads-action-detection.d.ts +6 -0
  43. package/dist/h5/ads/anti-cheating.d.ts +61 -0
  44. package/dist/h5/ads/index.d.ts +275 -0
  45. package/dist/h5/api/base.d.ts +13 -0
  46. package/dist/h5/api/get-system-info.d.ts +1 -0
  47. package/dist/h5/api/index.d.ts +4 -0
  48. package/dist/h5/api/lifecycle.d.ts +1 -0
  49. package/dist/h5/api/storage.d.ts +27 -0
  50. package/dist/h5/api/task.d.ts +1 -0
  51. package/dist/h5/bootstrap/index.d.ts +1 -0
  52. package/dist/h5/http/index.d.ts +33 -0
  53. package/dist/h5/http/utils/__tests__/uuid.test.d.ts +1 -0
  54. package/dist/h5/http/utils/__tests__/xua.test.d.ts +1 -0
  55. package/dist/h5/http/utils/index.d.ts +14 -0
  56. package/dist/h5/http/utils/session.d.ts +1 -0
  57. package/dist/h5/report/errors/index.d.ts +4 -0
  58. package/dist/h5/report/event-tracker.d.ts +8 -0
  59. package/dist/h5/report/index.d.ts +10 -0
  60. package/dist/h5/report/task-tracker.d.ts +14 -0
  61. package/dist/index.d.ts +3 -0
  62. package/dist/index.js +5026 -0
  63. package/dist/index.native.d.ts +2 -0
  64. package/dist/index.native.js +3743 -0
  65. package/dist/native/api/base.d.ts +13 -0
  66. package/dist/native/api/get-system-info.d.ts +1 -0
  67. package/dist/native/api/index.d.ts +7 -0
  68. package/dist/native/api/keyboard.d.ts +3 -0
  69. package/dist/native/api/lifecycle.d.ts +1 -0
  70. package/dist/native/api/login.d.ts +1 -0
  71. package/dist/native/api/request.d.ts +1 -0
  72. package/dist/native/api/storage.d.ts +25 -0
  73. package/dist/native/api/task.d.ts +1 -0
  74. package/dist/native/bootstrap/bridge.d.ts +4 -0
  75. package/dist/native/bootstrap/index.d.ts +1 -0
  76. package/dist/native/js-bridge/const.d.ts +5 -0
  77. package/dist/native/js-bridge/index.d.ts +2 -0
  78. package/dist/native/js-bridge/invoke.d.ts +21 -0
  79. package/dist/native/js-bridge/js-bridge.d.ts +6 -0
  80. package/dist/native/js-bridge/report.d.ts +63 -0
  81. package/dist/native/js-bridge/subscribe.d.ts +8 -0
  82. package/dist/native/js-bridge/types.d.ts +14 -0
  83. package/dist/native/js-bridge/utils.d.ts +17 -0
  84. package/dist/native/js-core/index.d.ts +3 -0
  85. package/dist/native/js-core/jolibox-js-core.d.ts +45 -0
  86. package/dist/native/js-core/message-port.d.ts +12 -0
  87. package/dist/native/js-core/utils.d.ts +7 -0
  88. package/dist/native/network/create-fetch.d.ts +27 -0
  89. package/dist/native/network/index.d.ts +11 -0
  90. package/dist/native/network/report.d.ts +15 -0
  91. package/dist/native/network/types.d.ts +61 -0
  92. package/dist/native/network/utils.d.ts +9 -0
  93. package/dist/native/report/errors/index.d.ts +4 -0
  94. package/dist/native/report/index.d.ts +10 -0
  95. package/dist/native/report/task-tracker.d.ts +20 -0
  96. package/dist/utils/index.d.ts +0 -0
  97. package/esbuild.config.js +66 -0
  98. package/implement.build.log +9 -0
  99. package/package.json +30 -0
  100. package/src/common/api-factory/index.ts +188 -0
  101. package/src/common/api-factory/validator/__tests__/validate/any.test.ts +68 -0
  102. package/src/common/api-factory/validator/__tests__/validate/array.test.ts +402 -0
  103. package/src/common/api-factory/validator/__tests__/validate/arraybuffer.test.ts +48 -0
  104. package/src/common/api-factory/validator/__tests__/validate/boolean.test.ts +27 -0
  105. package/src/common/api-factory/validator/__tests__/validate/enum.test.ts +106 -0
  106. package/src/common/api-factory/validator/__tests__/validate/function.test.ts +54 -0
  107. package/src/common/api-factory/validator/__tests__/validate/literal.test.ts +130 -0
  108. package/src/common/api-factory/validator/__tests__/validate/nullish.test.ts +41 -0
  109. package/src/common/api-factory/validator/__tests__/validate/number.test.ts +147 -0
  110. package/src/common/api-factory/validator/__tests__/validate/object.test.ts +131 -0
  111. package/src/common/api-factory/validator/__tests__/validate/or.test.ts +96 -0
  112. package/src/common/api-factory/validator/__tests__/validate/record.test.ts +274 -0
  113. package/src/common/api-factory/validator/__tests__/validate/string.test.ts +187 -0
  114. package/src/common/api-factory/validator/__tests__/validate/symbol.test.ts +23 -0
  115. package/src/common/api-factory/validator/__tests__/validate/tuple.test.ts +86 -0
  116. package/src/common/api-factory/validator/__tests__/validate/type-asserts.test.ts +13 -0
  117. package/src/common/api-factory/validator/__tests__/validate/utils.test.ts +44 -0
  118. package/src/common/api-factory/validator/index.ts +107 -0
  119. package/src/common/api-factory/validator/validate.ts +639 -0
  120. package/src/common/can-i-use.ts +19 -0
  121. package/src/common/context/index.ts +91 -0
  122. package/src/common/context/types.ts +5 -0
  123. package/src/common/context/url-parse.ts +63 -0
  124. package/src/common/http/index.ts +29 -0
  125. package/src/common/http/uuid.ts +11 -0
  126. package/src/common/http/xua.ts +79 -0
  127. package/src/common/report/base-tracker.ts +134 -0
  128. package/src/common/report/create-trace.ts +17 -0
  129. package/src/common/report/errors/error-types.ts +206 -0
  130. package/src/common/report/errors/index.ts +20 -0
  131. package/src/common/report/errors/report/index.ts +63 -0
  132. package/src/common/report/errors/report/listeners.ts +80 -0
  133. package/src/common/report/index.ts +3 -0
  134. package/src/common/report/task-track/index.ts +97 -0
  135. package/src/common/report/track.ts +49 -0
  136. package/src/common/report/types.ts +90 -0
  137. package/src/h5/ads/ads-action-detection.ts +31 -0
  138. package/src/h5/ads/anti-cheating.ts +244 -0
  139. package/src/h5/ads/index.ts +641 -0
  140. package/src/h5/api/base.ts +9 -0
  141. package/src/h5/api/get-system-info.ts +55 -0
  142. package/src/h5/api/index.ts +4 -0
  143. package/src/h5/api/lifecycle.ts +110 -0
  144. package/src/h5/api/storage.ts +173 -0
  145. package/src/h5/api/task.ts +197 -0
  146. package/src/h5/bootstrap/index.ts +16 -0
  147. package/src/h5/http/index.ts +189 -0
  148. package/src/h5/http/utils/__tests__/uuid.test.ts +16 -0
  149. package/src/h5/http/utils/__tests__/xua.test.ts +27 -0
  150. package/src/h5/http/utils/index.ts +19 -0
  151. package/src/h5/http/utils/session.ts +10 -0
  152. package/src/h5/report/errors/index.ts +40 -0
  153. package/src/h5/report/event-tracker.ts +40 -0
  154. package/src/h5/report/index.ts +56 -0
  155. package/src/h5/report/task-tracker.ts +35 -0
  156. package/src/index.native.ts +7 -0
  157. package/src/index.ts +9 -0
  158. package/src/native/api/base.ts +8 -0
  159. package/src/native/api/get-system-info.ts +41 -0
  160. package/src/native/api/index.ts +7 -0
  161. package/src/native/api/keyboard.ts +75 -0
  162. package/src/native/api/lifecycle.ts +76 -0
  163. package/src/native/api/login.ts +71 -0
  164. package/src/native/api/request.ts +154 -0
  165. package/src/native/api/storage.ts +287 -0
  166. package/src/native/api/task.ts +267 -0
  167. package/src/native/bootstrap/bridge.ts +59 -0
  168. package/src/native/bootstrap/index.ts +58 -0
  169. package/src/native/js-bridge/const.ts +11 -0
  170. package/src/native/js-bridge/index.ts +2 -0
  171. package/src/native/js-bridge/invoke.ts +210 -0
  172. package/src/native/js-bridge/js-bridge.ts +23 -0
  173. package/src/native/js-bridge/report.ts +311 -0
  174. package/src/native/js-bridge/subscribe.ts +50 -0
  175. package/src/native/js-bridge/types.ts +26 -0
  176. package/src/native/js-bridge/utils.ts +116 -0
  177. package/src/native/js-core/index.ts +4 -0
  178. package/src/native/js-core/jolibox-js-core.ts +188 -0
  179. package/src/native/js-core/message-port.ts +52 -0
  180. package/src/native/js-core/utils.ts +9 -0
  181. package/src/native/network/create-fetch.ts +237 -0
  182. package/src/native/network/index.ts +15 -0
  183. package/src/native/network/report.ts +58 -0
  184. package/src/native/network/types.ts +77 -0
  185. package/src/native/network/utils.ts +90 -0
  186. package/src/native/report/errors/index.ts +27 -0
  187. package/src/native/report/index.ts +51 -0
  188. package/src/native/report/task-tracker.ts +64 -0
  189. package/src/native/types/global.d.ts +26 -0
  190. package/src/native/types/native-method-map.d.ts +282 -0
  191. package/src/native/types/native-method.d.ts +30 -0
  192. package/src/utils/index.ts +0 -0
  193. package/tsconfig.json +18 -0
@@ -0,0 +1,4 @@
1
+ import './get-system-info';
2
+ import './lifecycle';
3
+ import './storage';
4
+ import './task';
@@ -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
+ });