@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,116 @@
1
+ export interface DataObj {
2
+ params?: Record<string, unknown>;
3
+ errorCode?: number;
4
+ __extra?: {
5
+ startTime: number;
6
+ type: string;
7
+ };
8
+ __nativeBuffers__?: NativeBufferElement[] | undefined;
9
+ }
10
+
11
+ interface NativeBufferElement {
12
+ key: string;
13
+ value?: ArrayBuffer;
14
+ base64?: string;
15
+ }
16
+
17
+ function isNativeBuffers(
18
+ x: unknown & { __nativeBuffers__?: NativeBufferElement[] | undefined }
19
+ ): x is { __nativeBuffers__?: NativeBufferElement[]; [k: string]: unknown } {
20
+ return Boolean(x?.__nativeBuffers__);
21
+ }
22
+
23
+ /**
24
+ * decodeFromUi8Base64
25
+ */
26
+ const decodeFromUi8Base64 = (string: string): ArrayBuffer => {
27
+ const base64String = atob(string);
28
+ const len = base64String.length;
29
+ const ui8aReader = new Uint8Array(len);
30
+ for (let i = 0; i < len; i++) {
31
+ ui8aReader[i] = base64String.charCodeAt(i);
32
+ }
33
+ return ui8aReader.buffer;
34
+ };
35
+
36
+ export function unpack(data: unknown): DataObj {
37
+ if (typeof data === 'string') {
38
+ try {
39
+ data = JSON.parse(data);
40
+ } catch {
41
+ return {};
42
+ }
43
+ }
44
+ if (typeof data !== 'object' || data === null) {
45
+ return {};
46
+ }
47
+
48
+ if (!isNativeBuffers(data)) return data as DataObj;
49
+
50
+ const nativeBuffers = data.__nativeBuffers__;
51
+ delete data.__nativeBuffers__;
52
+
53
+ if (nativeBuffers) {
54
+ for (let i = 0; i < nativeBuffers.length; i++) {
55
+ const item = nativeBuffers[i];
56
+ if (item) {
57
+ let tmp;
58
+ if (item.value) {
59
+ // Arraybuffer
60
+ tmp = item.value;
61
+ } else if (item.base64) {
62
+ tmp = decodeFromUi8Base64(item.base64);
63
+ }
64
+ if (typeof tmp !== 'undefined' && tmp instanceof ArrayBuffer) {
65
+ data[item.key] = tmp;
66
+ }
67
+ }
68
+ }
69
+ }
70
+
71
+ return data;
72
+ }
73
+
74
+ const encodeToUi8Base64 = (arrayBuffer: ArrayBuffer): string => {
75
+ let string = '';
76
+ const ui8aReader = new Uint8Array(arrayBuffer);
77
+ const len = ui8aReader.byteLength;
78
+ for (let i = 0; i < len; i++) {
79
+ string += String.fromCharCode(ui8aReader[i]);
80
+ }
81
+ return btoa(string);
82
+ };
83
+
84
+ export function pack(_data = {}, useArrayBuffer = false): Record<string, unknown> {
85
+ const data = _data as Record<string, unknown>;
86
+ type ArrayBufferType =
87
+ | {
88
+ value: ArrayBuffer;
89
+ key: string;
90
+ base64?: undefined;
91
+ }
92
+ | {
93
+ base64: string;
94
+ key: string;
95
+ value?: undefined;
96
+ };
97
+ const needTransAttrs: ArrayBufferType[] = [];
98
+ for (const [key, item] of Object.entries(data)) {
99
+ if (item !== undefined && item instanceof ArrayBuffer && item.byteLength !== undefined) {
100
+ const obj: ArrayBufferType = useArrayBuffer
101
+ ? { value: item, key }
102
+ : {
103
+ base64: encodeToUi8Base64(item),
104
+ key
105
+ };
106
+ needTransAttrs.push(obj);
107
+ // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
108
+ delete data[key];
109
+ }
110
+ }
111
+
112
+ if (needTransAttrs.length > 0) {
113
+ data.__nativeBuffers__ = needTransAttrs;
114
+ }
115
+ return data;
116
+ }
@@ -0,0 +1,4 @@
1
+ export { joliboxJSCore, RuntimeLoader } from './jolibox-js-core';
2
+
3
+ export { messagePort, initMessagePort } from './message-port';
4
+ export { normalizeParams } from './utils';
@@ -0,0 +1,188 @@
1
+ import { InternalInvokeNativeError } from '@jolibox/common';
2
+ // import { normalizeParams } from './utils';
3
+ import { Env } from '@jolibox/types';
4
+ import { reportError } from '@/common/report/errors/report';
5
+
6
+ declare const globalThis: {
7
+ joliboxJSCore?: JoliboxJSCore;
8
+ };
9
+
10
+ interface JoliboxJSCore {
11
+ // publish: (event: string, params: string, webviewIds: string) => void;
12
+ invoke: (method: string, params: string, callbackId: number) => string | void;
13
+ /** 安卓: webview 没有 call, service 有 */
14
+ call?: (method: string, params: Record<string, unknown>, callbackId: number) => string | void;
15
+ onDocumentReady: (path: string) => void;
16
+ }
17
+
18
+ export let joliboxJSCore: jsb.JSCore | undefined;
19
+
20
+ declare global {
21
+ interface Window {
22
+ JoliAndroidSDKBridge?: {
23
+ invoke: (invokeString: string) => void;
24
+ onDocumentReady: (paramsstr: string) => void;
25
+ doExit: (uuidString: string) => void;
26
+ };
27
+ webkit?: {
28
+ messageHandlers: {
29
+ invoke: {
30
+ postMessage: (params: { event: string; callbackId: number; paramsString: string }) => void;
31
+ };
32
+ publish: {
33
+ postMessage: (params: { event: string; webviewIds: string; paramsString: string }) => void;
34
+ };
35
+ onDocumentReady: {
36
+ postMessage: (params: { path: string }) => void;
37
+ };
38
+ doExit: {
39
+ postMessage: (params: { uuid: string; shouldInterrupt: boolean }) => void;
40
+ };
41
+ };
42
+ };
43
+ }
44
+ }
45
+
46
+ export const RuntimeLoader = {
47
+ trigger() {
48
+ // noop
49
+ },
50
+ exit(): boolean {
51
+ //noop
52
+ return false; // 默认不打断退出
53
+ },
54
+ onReady(fn: () => void) {
55
+ RuntimeLoader.trigger = fn;
56
+ },
57
+ doExit(fn: () => boolean) {
58
+ RuntimeLoader.exit = fn;
59
+ }
60
+ };
61
+
62
+ const env = (): Env | undefined => {
63
+ const res = window.prompt(
64
+ 'invoke',
65
+ JSON.stringify({
66
+ event: 'envSync',
67
+ paramsString: JSON.stringify({})
68
+ })
69
+ );
70
+ if (!res) {
71
+ reportError(new InternalInvokeNativeError(`native env failed`));
72
+ } else {
73
+ const { data } = JSON.parse(res);
74
+ return data ?? undefined;
75
+ }
76
+ };
77
+
78
+ if (window.webkit) {
79
+ const _joliboxJSCore = window.webkit.messageHandlers;
80
+ const onDocumentReady = (path = '') => {
81
+ RuntimeLoader.trigger();
82
+ _joliboxJSCore.onDocumentReady.postMessage({ path });
83
+ };
84
+ const doExit = (uuid: string) => {
85
+ const shouldInterrupt = RuntimeLoader.exit();
86
+ _joliboxJSCore.doExit.postMessage({ uuid, shouldInterrupt });
87
+ };
88
+
89
+ joliboxJSCore = {
90
+ onDocumentReady,
91
+ doExit,
92
+ invoke(method, params, callbackId) {
93
+ _joliboxJSCore.invoke.postMessage({
94
+ event: method,
95
+ paramsString: params,
96
+ callbackId
97
+ });
98
+ },
99
+ // publish(event, params, webviewIds) {
100
+ // const data = normalizeParams(params as Record<string, unknown>, 'joliboxJSCore');
101
+ // _joliboxJSCore.publish.postMessage({
102
+ // event,
103
+ // paramsString: JSON.stringify(data),
104
+ // webviewIds: JSON.stringify(webviewIds)
105
+ // });
106
+ // },
107
+ call(method: string, params: Record<string, unknown>, callbackId) {
108
+ const res = window.prompt(
109
+ 'invoke',
110
+ JSON.stringify({
111
+ event: method,
112
+ paramsString: JSON.stringify(params),
113
+ callbackId
114
+ })
115
+ );
116
+ if (res) {
117
+ return JSON.parse(res);
118
+ }
119
+ }
120
+ };
121
+
122
+ // do not expose invoke/ publish to user
123
+ const devCore = { onDocumentReady, env };
124
+
125
+ //eslint-disable-next-line @typescript-eslint/ban-ts-comment
126
+ // @ts-ignore
127
+ globalThis.joliboxJSCore = {
128
+ ...devCore
129
+ };
130
+ }
131
+
132
+ // Android
133
+ if (window.JoliAndroidSDKBridge) {
134
+ const _joliboxJSCore = window.JoliAndroidSDKBridge;
135
+ const onDocumentReady = (path = '') => {
136
+ RuntimeLoader.trigger();
137
+ _joliboxJSCore.onDocumentReady(JSON.stringify({ path }));
138
+ };
139
+
140
+ const doExit = (uuid: string) => {
141
+ const shouldInterrupt = RuntimeLoader.exit();
142
+ _joliboxJSCore.doExit(JSON.stringify({ uuid, shouldInterrupt }));
143
+ };
144
+
145
+ joliboxJSCore = {
146
+ onDocumentReady,
147
+ invoke(method, params, callbackId) {
148
+ _joliboxJSCore.invoke(
149
+ JSON.stringify({
150
+ event: method,
151
+ paramsString: params,
152
+ callbackId
153
+ })
154
+ );
155
+ },
156
+ doExit,
157
+ // publish(event, params, webviewIds) {
158
+ // const data = normalizeParams(params as Record<string, unknown>, 'joliboxJSCore');
159
+ // _joliboxJSCore.publish({
160
+ // event,
161
+ // paramsString: JSON.stringify(data),
162
+ // webviewIds: JSON.stringify(webviewIds)
163
+ // });
164
+ // },
165
+ call(method: string, params: Record<string, unknown>, callbackId) {
166
+ const res = window.prompt(
167
+ 'invoke',
168
+ JSON.stringify({
169
+ event: method,
170
+ paramsString: JSON.stringify(params),
171
+ callbackId
172
+ })
173
+ );
174
+ if (res) {
175
+ return JSON.parse(res);
176
+ }
177
+ }
178
+ };
179
+
180
+ // do not expose invoke/ publish to user
181
+ const devCore = { onDocumentReady, env };
182
+
183
+ //eslint-disable-next-line @typescript-eslint/ban-ts-comment
184
+ // @ts-ignore
185
+ globalThis.joliboxJSCore = {
186
+ ...devCore
187
+ };
188
+ }
@@ -0,0 +1,52 @@
1
+ import { normalizeParams } from './utils';
2
+ import { AnyFunction } from '@jolibox/types';
3
+
4
+ declare const globalThis: {
5
+ onmessage?: (msg: MessageEvent) => void;
6
+ ttJSBridge: {
7
+ invokeHandler: AnyFunction;
8
+ subscribeHandler: AnyFunction;
9
+ };
10
+ };
11
+
12
+ interface MessageEvent {
13
+ data: string;
14
+ ports: MessagePort[];
15
+ }
16
+
17
+ interface MessagePort {
18
+ onmessage: (msg: MessageEvent) => void;
19
+ postMessage: (msg: string) => void;
20
+ publish: (event: string, data: Record<string, unknown>) => void;
21
+ }
22
+
23
+ type PublishEvent = ['publish', string, string];
24
+ type InvokeEvent = ['invoke', number, string];
25
+
26
+ export let messagePort: MessagePort | undefined;
27
+
28
+ export function initMessagePort() {
29
+ globalThis.onmessage = function (msg) {
30
+ if (msg.data !== 'msg:setup') {
31
+ return;
32
+ }
33
+
34
+ [messagePort] = msg.ports;
35
+ messagePort.onmessage = function (message) {
36
+ const data: PublishEvent | InvokeEvent = JSON.parse(message.data);
37
+ if (data[0] === 'publish') {
38
+ globalThis.ttJSBridge.subscribeHandler(data[1], data[2]);
39
+ } else if (data[0] === 'invoke') {
40
+ globalThis.ttJSBridge.invokeHandler(data[1], data[2]);
41
+ }
42
+ };
43
+
44
+ messagePort.publish = function (event, params) {
45
+ const data = normalizeParams(params as Record<string, unknown>, 'messagePort');
46
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
47
+ messagePort!.postMessage(JSON.stringify(['publish', event, JSON.stringify(data)]));
48
+ };
49
+
50
+ messagePort.postMessage('msg:setup:ok');
51
+ };
52
+ }
@@ -0,0 +1,9 @@
1
+ export function normalizeParams(params: Record<string, unknown>, type: string) {
2
+ return {
3
+ params,
4
+ __extra: {
5
+ startTime: Date.now(),
6
+ type
7
+ }
8
+ };
9
+ }
@@ -0,0 +1,237 @@
1
+ import { isString, logger, Deferred, isObject, hostEmitter } from '@jolibox/common';
2
+ import { reportNetworkAPI } from './report';
3
+ import { RequestFrom } from './types';
4
+ import { FetchResponse, FetchOptions } from './types';
5
+ import { invokeNative, onNative } from '@/native/bootstrap/bridge';
6
+ import { AnyFunction } from '@jolibox/types';
7
+ import { reportError } from '@/common/report/errors/report';
8
+ import { createAPIError } from '@/common/report/errors';
9
+
10
+ type Fetch = <T>(
11
+ url: string,
12
+ innerOptions?: FetchOptions & {
13
+ baseUrl?: string;
14
+ }
15
+ ) => Promise<{
16
+ url: string;
17
+ timeout?: number;
18
+ method: string;
19
+ response: FetchResponse<T>;
20
+ }>;
21
+
22
+ type PublicFetch = <T>(
23
+ url: string,
24
+ options?: FetchOptions
25
+ ) => Promise<{
26
+ url: string;
27
+ timeout?: number;
28
+ method: string;
29
+ response: FetchResponse<T>;
30
+ }>;
31
+
32
+ const processUrl = (url: string, options?: FetchOptions & { baseUrl?: string }): string => {
33
+ if (/^https?:\/\//.test(url)) {
34
+ return url;
35
+ }
36
+ const query = options?.query;
37
+ const searchParams = new URLSearchParams(query);
38
+ const search = searchParams.toString();
39
+ return options?.baseUrl
40
+ ? `${options.baseUrl}${url}${search ? `?${search}` : ''}`
41
+ : `${url}${search ? `?${search}` : ''}`;
42
+ };
43
+
44
+ export function createFetch(
45
+ createMethod: 'createRequestTaskSync',
46
+ operateMethod: 'operateRequestTaskSync',
47
+ options?: {
48
+ baseUrl?: string;
49
+ type: 'public';
50
+ }
51
+ ): PublicFetch;
52
+
53
+ export function createFetch(
54
+ createMethod: 'createRequestTaskSync',
55
+ operateMethod: 'operateRequestTaskSync',
56
+ options?: {
57
+ baseUrl?: string;
58
+ type: 'inner';
59
+ defaultHeaders?: Record<string, string>;
60
+ }
61
+ ): Fetch;
62
+
63
+ export function createFetch(
64
+ createMethod: 'createRequestTaskSync',
65
+ operateMethod: 'operateRequestTaskSync',
66
+ options?: {
67
+ baseUrl?: string;
68
+ type: 'inner' | 'public';
69
+ defaultHeaders?: Record<string, string>;
70
+ }
71
+ ) {
72
+ const promiseMap = new Map<string, { resolve: AnyFunction; reject: AnyFunction }>();
73
+ const baseUrl = options?.baseUrl ?? `https://api.jolibox.com`;
74
+ const type = options?.type ?? 'public';
75
+ const defaultHeaders = options?.defaultHeaders ?? {};
76
+
77
+ onNative('onRequestTaskStateChange', (res) => {
78
+ if (typeof res.requestTaskId !== 'string') return;
79
+ const task = promiseMap.get(res.requestTaskId);
80
+ if (!task) return;
81
+
82
+ if (res.state === 'success') {
83
+ const { requestTaskId, state, ...rest } = res;
84
+ task.resolve(rest);
85
+ promiseMap.delete(requestTaskId);
86
+ } else if (res.state === 'fail') {
87
+ const { requestTaskId, state, ...rest } = res;
88
+ task.reject(rest);
89
+ promiseMap.delete(requestTaskId);
90
+ } else {
91
+ logger.warn(`onRequestTaskStateChange unknown event`, res);
92
+ }
93
+ });
94
+
95
+ hostEmitter.on('onLoginComplete', ({ isLogin, token }) => {
96
+ if (isLogin && token) {
97
+ defaultHeaders['X-JOLI-TOKEN'] = token;
98
+ }
99
+ });
100
+
101
+ const fetch: Fetch = async (originUrl, options = {}) => {
102
+ const startTime = Date.now();
103
+
104
+ const url = processUrl(originUrl, { ...options, baseUrl });
105
+ const {
106
+ method = 'GET',
107
+ responseType = 'text',
108
+ dataType = 'json',
109
+ timeout,
110
+ enableCache = false,
111
+ appendHostCookie = true
112
+ } = options;
113
+
114
+ const header = Object.assign({ 'content-type': 'application/json' }, defaultHeaders, options.header);
115
+
116
+ // modify params
117
+ const params = {
118
+ url,
119
+ method,
120
+ header,
121
+ enableCache,
122
+ responseType,
123
+ appendHostCookie
124
+ } as any;
125
+
126
+ if (method == 'POST' || method == 'PUT') {
127
+ const data = normalizeData(options.data, header['content-type']);
128
+ params['data'] = data;
129
+ }
130
+
131
+ if (timeout) {
132
+ Object.assign(params, { timeout });
133
+ }
134
+ const {
135
+ data: { requestTaskId }
136
+ } = invokeNative(createMethod, params);
137
+
138
+ if (typeof requestTaskId !== 'string') {
139
+ throw createAPIError({
140
+ code: -1,
141
+ msg: 'requestTaskId is not a string'
142
+ });
143
+ }
144
+
145
+ const report = (state: 'success' | 'fail', response: unknown) => {
146
+ reportNetworkAPI('request', url, {
147
+ state,
148
+ startTime,
149
+ endTime: Date.now(),
150
+ params,
151
+ response: response as FetchResponse,
152
+ requestId: requestTaskId,
153
+ requestFrom: type == 'public' ? RequestFrom.PUBLIC : RequestFrom.INNER
154
+ });
155
+ };
156
+
157
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
158
+ const { resolve, reject, promise } = new Deferred<FetchResponse<any>>();
159
+ promiseMap.set(requestTaskId, { resolve, reject });
160
+
161
+ try {
162
+ const res = await promise;
163
+ report('success', res);
164
+ let { data } = res;
165
+ if (dataType === 'json' && typeof data === 'string') {
166
+ data = parseJSON(data);
167
+ }
168
+ return {
169
+ url,
170
+ timeout,
171
+ method,
172
+ response: { ...res, data }
173
+ };
174
+ } catch (err: unknown) {
175
+ const error = err as {
176
+ errMsg?: string;
177
+ errNo?: number;
178
+ errorType?: string;
179
+ errorCode?: number;
180
+ prefetchDetail?: number;
181
+ isPrefetch?: boolean;
182
+ };
183
+
184
+ if (isObject(error)) {
185
+ const { errMsg, prefetchDetail, isPrefetch, errNo } = error;
186
+ if (isString(errMsg)) {
187
+ report('fail', {
188
+ errMsg,
189
+ isPrefetch,
190
+ prefetchDetail
191
+ });
192
+ reportError(createAPIError({ code: -1, msg: errMsg }, { errNo: errNo as number, errMsg }));
193
+ }
194
+ }
195
+ throw err;
196
+ }
197
+ };
198
+
199
+ return fetch;
200
+ }
201
+
202
+ export function parseJSON(data: string) {
203
+ try {
204
+ //
205
+ // 之所以要 trim, 是因为有些开发者不是按照标准的 application/json 返回的, 而是使用 text/html 返回
206
+ // 而 text/html 返回的时候前后有可能出现 &#65279 字符, 导致 JSON.parse 失败
207
+ return JSON.parse(data.trim());
208
+ } catch {
209
+ return data;
210
+ }
211
+ }
212
+
213
+ export function normalizeData(data: unknown, contentType = 'application/json') {
214
+ const type = contentType.toLowerCase();
215
+
216
+ if (data === undefined) {
217
+ return '';
218
+ }
219
+
220
+ if (typeof data === 'string' || data instanceof ArrayBuffer) {
221
+ return data;
222
+ }
223
+
224
+ if (type.includes('application/x-www-form-urlencoded')) {
225
+ return JSON.stringify(data as JSON);
226
+ }
227
+
228
+ if (type.includes('application/json')) {
229
+ return JSON.stringify(data);
230
+ }
231
+
232
+ if (typeof data === 'object') {
233
+ return JSON.stringify(data);
234
+ }
235
+
236
+ return String(data);
237
+ }
@@ -0,0 +1,15 @@
1
+ import { xUserAgent } from '@/common/http/xua';
2
+ import { createFetch } from './create-fetch';
3
+ import { context } from '@/common/context';
4
+
5
+ /**
6
+ * inner fetch
7
+ */
8
+ export const innerFetch = createFetch('createRequestTaskSync', 'operateRequestTaskSync', {
9
+ type: 'inner',
10
+ baseUrl: context.testMode ? 'https://stg-api.jolibox.com' : 'https://api.jolibox.com',
11
+ defaultHeaders: {
12
+ 'x-user-agent': xUserAgent(),
13
+ 'X-JOLI-TOKEN': context.hostUserInfo?.token ?? ''
14
+ }
15
+ });
@@ -0,0 +1,58 @@
1
+ import { FetchResponse, DownLoadResponse, UpLoadResponse, RequestFrom } from './types';
2
+
3
+ import { track } from '@/native/report';
4
+
5
+ type NetworkResponse = FetchResponse | DownLoadResponse | UpLoadResponse;
6
+ interface ReportNetworkOptions {
7
+ state: 'success' | 'fail';
8
+ params: Record<string, unknown>;
9
+ response: NetworkResponse;
10
+ startTime: number;
11
+ endTime: number;
12
+ callbackStartTime?: number;
13
+ callbackEndTime?: number;
14
+ requestId?: string;
15
+ requestFrom?: RequestFrom; // 区分内部/外部请求
16
+ }
17
+
18
+ interface RequestResultData {
19
+ duration: number;
20
+ request_type: string;
21
+ url: string;
22
+ result: string;
23
+ error_msg: unknown;
24
+ socket_reused?: number; // reused
25
+ joli_request_number?: number; // 请求序号
26
+ request_from?: string; // 'public' / 'inner'
27
+ }
28
+ // report max count = 10
29
+ let requestNumber = 0;
30
+ const requestNumberLimit = 10;
31
+
32
+ export function reportNetworkAPI(method: string, url: string, options: ReportNetworkOptions): void {
33
+ const { response, startTime, endTime, requestFrom } = options;
34
+ const { errMsg = '', profile = {} } = response as FetchResponse;
35
+
36
+ const duration = endTime - startTime;
37
+
38
+ const trackData: RequestResultData = {
39
+ duration,
40
+ request_type: method,
41
+ url: url.split('?')[0],
42
+ result: options.state,
43
+ error_msg: options.state === 'fail' ? errMsg : '',
44
+ socket_reused: profile.socketReused ? 1 : 0,
45
+ request_from: requestFrom
46
+ };
47
+
48
+ // 用户请求上报最多10个,内部的全部上报
49
+ if (
50
+ (requestFrom === RequestFrom.PUBLIC && requestNumber < requestNumberLimit) ||
51
+ requestFrom === RequestFrom.INNER
52
+ ) {
53
+ trackData.joli_request_number = requestNumber++;
54
+ setTimeout(() => {
55
+ track('joliboxNetRequestResult', trackData as unknown as Record<string, unknown>);
56
+ }, 500);
57
+ }
58
+ }