@jolibox/implement 1.1.11-beta.10 → 1.1.11-beta.11
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/.rush/temp/package-deps_build.json +6 -6
- package/dist/common/context/index.d.ts +1 -0
- package/dist/index.js +2 -2
- package/dist/index.native.js +6 -6
- package/dist/native/network/create-fetch.d.ts +1 -0
- package/implement.build.log +2 -2
- package/package.json +3 -3
- package/src/common/context/index.ts +3 -0
- package/src/native/api/request.ts +19 -10
- package/src/native/bootstrap/index.ts +97 -50
- package/src/native/network/create-fetch.ts +1 -0
- package/src/native/network/utils.ts +13 -6
package/implement.build.log
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Invoking: npm run clean && npm run build:esm && tsc
|
|
2
2
|
|
|
3
|
-
> @jolibox/implement@1.1.11-beta.
|
|
3
|
+
> @jolibox/implement@1.1.11-beta.11 clean
|
|
4
4
|
> rimraf ./dist
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
> @jolibox/implement@1.1.11-beta.
|
|
7
|
+
> @jolibox/implement@1.1.11-beta.11 build:esm
|
|
8
8
|
> BUILD_VERSION=$(node -p "require('./package.json').version") node esbuild.config.js --format=esm
|
|
9
9
|
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jolibox/implement",
|
|
3
3
|
"description": "This project is Jolibox JS-SDk implement for Native && H5",
|
|
4
|
-
"version": "1.1.11-beta.
|
|
4
|
+
"version": "1.1.11-beta.11",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"typings": "dist/index.d.ts",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"@jolibox/common": "1.1.11-beta.
|
|
10
|
-
"@jolibox/types": "1.1.11-beta.
|
|
9
|
+
"@jolibox/common": "1.1.11-beta.11",
|
|
10
|
+
"@jolibox/types": "1.1.11-beta.11",
|
|
11
11
|
"localforage": "1.10.0",
|
|
12
12
|
"@jolibox/ui": "1.0.0",
|
|
13
13
|
"web-vitals": "4.2.4"
|
|
@@ -100,6 +100,9 @@ const wrapContext = () => {
|
|
|
100
100
|
get from(): number | undefined {
|
|
101
101
|
return payloadJson?.__from;
|
|
102
102
|
},
|
|
103
|
+
get baseApiHost(): string {
|
|
104
|
+
return testMode ? 'https://stg-api.jolibox.com' : 'https://api.jolibox.com';
|
|
105
|
+
},
|
|
103
106
|
onEnvConfigChanged: (newConfig: Partial<Env>) => {
|
|
104
107
|
mergeWith(env, newConfig, mergeArray);
|
|
105
108
|
},
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import { createAPIError } from '@/common/report/errors';
|
|
2
2
|
import { createFetch } from '../network/create-fetch';
|
|
3
|
-
import {
|
|
3
|
+
import { createSyncAPI, registerCanIUse, t } from './base';
|
|
4
4
|
import { dirtyURL, normalizeHeader, normalizeMethod, normalizeTimeout } from '../network/utils';
|
|
5
5
|
import { BaseError, createCommands, Deferred, wrapUserFunction } from '@jolibox/common';
|
|
6
6
|
import { AnyFunction, ResponseType } from '@jolibox/types';
|
|
7
7
|
import { reportError } from '@/common/report/errors/report';
|
|
8
8
|
import { FetchOptions } from '../network/types';
|
|
9
|
+
import { context } from '@/common/context';
|
|
9
10
|
|
|
10
11
|
const LIMIT = 15;
|
|
11
12
|
|
|
12
13
|
const publicFetch = createFetch('createRequestTaskSync', 'operateRequestTaskSync', {
|
|
13
|
-
type: 'public'
|
|
14
|
+
type: 'public',
|
|
15
|
+
baseUrl: context.baseApiHost
|
|
14
16
|
});
|
|
15
17
|
|
|
16
18
|
/** current active count */
|
|
@@ -41,12 +43,12 @@ const request = (_params: unknown) => {
|
|
|
41
43
|
// noop
|
|
42
44
|
};
|
|
43
45
|
|
|
44
|
-
const _request =
|
|
46
|
+
const _request = createSyncAPI('request', {
|
|
45
47
|
paramsSchema: t.tuple(
|
|
46
48
|
t.object({
|
|
47
49
|
url: t.string(),
|
|
48
50
|
method: t.string(),
|
|
49
|
-
|
|
51
|
+
headers: t.object(),
|
|
50
52
|
data: t.object().optional(),
|
|
51
53
|
query: t.object().optional(),
|
|
52
54
|
dataType: t.string().default('json'),
|
|
@@ -68,9 +70,10 @@ const request = (_params: unknown) => {
|
|
|
68
70
|
if (deferred.state !== 'pending') {
|
|
69
71
|
return;
|
|
70
72
|
}
|
|
73
|
+
|
|
71
74
|
const { data, dataType, responseType, enableCache, appendHostCookie } = params;
|
|
72
75
|
|
|
73
|
-
const header = normalizeHeader(params.
|
|
76
|
+
const header = normalizeHeader(params.headers);
|
|
74
77
|
const method = normalizeMethod(params.method);
|
|
75
78
|
const timeout = normalizeTimeout(params.timeout);
|
|
76
79
|
const url = dirtyURL(params.url, method, data);
|
|
@@ -89,15 +92,21 @@ const request = (_params: unknown) => {
|
|
|
89
92
|
|
|
90
93
|
if (timeout) _params['timeout'] = timeout;
|
|
91
94
|
|
|
92
|
-
const task = publicFetch<
|
|
93
|
-
|
|
95
|
+
const task = publicFetch<
|
|
96
|
+
string | ArrayBuffer | JSON | { status: number; data: string | ArrayBuffer | JSON }
|
|
97
|
+
>(url, _params);
|
|
94
98
|
{
|
|
95
99
|
const { response } = await task;
|
|
96
100
|
const { code, data, message } = response;
|
|
97
|
-
|
|
101
|
+
if (data && typeof data === 'object' && 'status' in data && data.status !== 200) {
|
|
102
|
+
throw createAPIError({
|
|
103
|
+
code: data.status || -1,
|
|
104
|
+
msg: `request:fail status ${data.status}`
|
|
105
|
+
});
|
|
106
|
+
}
|
|
98
107
|
deferred.resolve({
|
|
99
108
|
code: (code ?? 'SUCCESS') as ResponseType,
|
|
100
|
-
data,
|
|
109
|
+
data: data as string | ArrayBuffer | JSON,
|
|
101
110
|
message: message ?? 'request:ok'
|
|
102
111
|
});
|
|
103
112
|
|
|
@@ -132,7 +141,7 @@ const request = (_params: unknown) => {
|
|
|
132
141
|
}
|
|
133
142
|
});
|
|
134
143
|
|
|
135
|
-
_request(_params);
|
|
144
|
+
_request(_params as Parameters<typeof _request>[0]);
|
|
136
145
|
|
|
137
146
|
return {
|
|
138
147
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { invokeNative, onNative, RuntimeLoader
|
|
1
|
+
import { invokeNative, onNative, RuntimeLoader } from './bridge';
|
|
2
2
|
import { joliboxJSCore } from '../js-core';
|
|
3
3
|
import { context } from '@/common/context';
|
|
4
4
|
import { hostEmitter, isBoolean } from '@jolibox/common';
|
|
@@ -6,65 +6,52 @@ import { taskTracker, track } from '../report';
|
|
|
6
6
|
import { initializeNativeEnv } from './init-env';
|
|
7
7
|
import { adEventEmitter } from '@/common/ads';
|
|
8
8
|
import { openRetentionSchema } from '../ui/retention';
|
|
9
|
+
import { innerFetch } from '../network';
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
});
|
|
11
|
+
interface IBasicMetaConfig {
|
|
12
|
+
canShowRecommended: boolean;
|
|
13
|
+
}
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
timestamp: Date.now()
|
|
19
|
-
});
|
|
20
|
-
cleanStyles?.();
|
|
21
|
-
taskTracker.close(Date.now() - start_timestamp);
|
|
22
|
-
};
|
|
15
|
+
/**
|
|
16
|
+
* 全局变量
|
|
17
|
+
*/
|
|
23
18
|
|
|
24
19
|
/**
|
|
25
|
-
*
|
|
26
|
-
* 1. 如果正在展示广告,则禁止退出
|
|
27
|
-
* 2. 如果指定退出挽留逻辑,则按照指定逻辑运行
|
|
28
|
-
* 3. 如果退出挽留逻辑返回 true,则按照指定逻辑运行
|
|
29
|
-
* 4. 否则,按照默认逻辑运行
|
|
20
|
+
* 清除safari jolibox样式
|
|
30
21
|
*/
|
|
31
|
-
|
|
32
|
-
if (isAdShowing) {
|
|
33
|
-
return true; // Forbid exit on watching ads
|
|
34
|
-
}
|
|
22
|
+
let cleanStyles: () => void;
|
|
35
23
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
doActualExit();
|
|
41
|
-
}
|
|
42
|
-
return context.shouldInterupt;
|
|
43
|
-
}
|
|
24
|
+
/**
|
|
25
|
+
* 启动时间戳
|
|
26
|
+
*/
|
|
27
|
+
let start_timestamp: number;
|
|
44
28
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
29
|
+
/**
|
|
30
|
+
* 是否展示广告
|
|
31
|
+
*/
|
|
32
|
+
let isAdShowing = false;
|
|
50
33
|
|
|
51
|
-
|
|
52
|
-
//埋点上报
|
|
53
|
-
doActualExit();
|
|
54
|
-
return false;
|
|
55
|
-
});
|
|
34
|
+
let baskcMeta: IBasicMetaConfig | null = null;
|
|
56
35
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
isAdShowing = isShowing;
|
|
60
|
-
if (isBoolean(isAdShowing)) {
|
|
61
|
-
invokeNative('updateContainerConfigSync', {
|
|
62
|
-
displayCapsuleButton: !isAdShowing,
|
|
63
|
-
webviewId: context.webviewId
|
|
64
|
-
});
|
|
65
|
-
}
|
|
36
|
+
RuntimeLoader.onReady(() => {
|
|
37
|
+
// TODO: merge some env config
|
|
66
38
|
});
|
|
67
39
|
|
|
40
|
+
/**
|
|
41
|
+
* 添加广告展示监听
|
|
42
|
+
*/
|
|
43
|
+
function addShowAdListener() {
|
|
44
|
+
adEventEmitter.on('isAdShowing', (isShowing) => {
|
|
45
|
+
isAdShowing = isShowing;
|
|
46
|
+
if (isBoolean(isAdShowing)) {
|
|
47
|
+
invokeNative('updateContainerConfigSync', {
|
|
48
|
+
displayCapsuleButton: !isAdShowing,
|
|
49
|
+
webviewId: context.webviewId
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
68
55
|
/**
|
|
69
56
|
* The DOMContentLoaded event might be triggered very early,
|
|
70
57
|
* so the global loaded listener should be executed during the bootstrap process.
|
|
@@ -105,11 +92,71 @@ function addGameServiceReadyListener() {
|
|
|
105
92
|
joliboxJSCore?.doExit(uuid);
|
|
106
93
|
});
|
|
107
94
|
}
|
|
108
|
-
|
|
95
|
+
|
|
96
|
+
function addDoExitLoader() {
|
|
97
|
+
/**
|
|
98
|
+
* 退出逻辑
|
|
99
|
+
* 1. 如果正在展示广告,则禁止退出
|
|
100
|
+
* 2. 如果指定退出挽留逻辑,则按照指定逻辑运行
|
|
101
|
+
* 3. 如果退出挽留逻辑返回 true,则按照指定逻辑运行
|
|
102
|
+
* 4. 否则,按照默认逻辑运行
|
|
103
|
+
*/
|
|
104
|
+
|
|
105
|
+
const doActualExit = () => {
|
|
106
|
+
//埋点上报
|
|
107
|
+
track('onBeforeExit', {
|
|
108
|
+
timestamp: Date.now()
|
|
109
|
+
});
|
|
110
|
+
cleanStyles?.();
|
|
111
|
+
taskTracker.close(Date.now() - start_timestamp);
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
RuntimeLoader.doExit(async () => {
|
|
115
|
+
if (isAdShowing) {
|
|
116
|
+
return true; // Forbid exit on watching ads
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// 指定退出挽留逻辑,则按照指定逻辑运行
|
|
120
|
+
if (isBoolean(context.shouldInterupt)) {
|
|
121
|
+
// 不需要打断退出,上报埋点
|
|
122
|
+
if (!context.shouldInterupt) {
|
|
123
|
+
doActualExit();
|
|
124
|
+
}
|
|
125
|
+
return context.shouldInterupt;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (baskcMeta?.canShowRecommended) {
|
|
129
|
+
const stay = await openRetentionSchema();
|
|
130
|
+
if (stay) {
|
|
131
|
+
// 挽留成功,打断退出
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// 退出,对应上报
|
|
137
|
+
//埋点上报
|
|
138
|
+
doActualExit();
|
|
139
|
+
return false;
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
async function fetchMetaConfig() {
|
|
144
|
+
const url = `${context.baseApiHost}/api/fe-configs/js-sdk/basic-meta`;
|
|
145
|
+
const {
|
|
146
|
+
response: { data }
|
|
147
|
+
} = await innerFetch<IBasicMetaConfig>(url);
|
|
148
|
+
|
|
149
|
+
if (data) {
|
|
150
|
+
baskcMeta = data;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
109
153
|
|
|
110
154
|
export function config(): void {
|
|
111
155
|
start_timestamp = Date.now();
|
|
112
156
|
addGameServiceReadyListener();
|
|
157
|
+
addShowAdListener();
|
|
158
|
+
addDoExitLoader();
|
|
113
159
|
addWebviewReadyListener();
|
|
160
|
+
fetchMetaConfig();
|
|
114
161
|
cleanStyles = initializeNativeEnv();
|
|
115
162
|
}
|
|
@@ -79,12 +79,19 @@ export function dirtyURL(url: string, method: HTTPMethod, data?: unknown) {
|
|
|
79
79
|
|
|
80
80
|
if (!isObject(data)) return url;
|
|
81
81
|
|
|
82
|
-
const [
|
|
82
|
+
const [baseUrl, search = ''] = url.split('?');
|
|
83
83
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
...data
|
|
87
|
-
});
|
|
84
|
+
// Parse existing query parameters
|
|
85
|
+
const dataParams = new URLSearchParams(search);
|
|
88
86
|
|
|
89
|
-
|
|
87
|
+
// Add new parameters from data object
|
|
88
|
+
for (const [key, value] of Object.entries(data)) {
|
|
89
|
+
if (value !== undefined && value !== null) {
|
|
90
|
+
dataParams.append(key, String(value));
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const queryString = dataParams.toString();
|
|
95
|
+
|
|
96
|
+
return queryString ? `${baseUrl}?${queryString}` : baseUrl;
|
|
90
97
|
}
|