@jolibox/sdk 1.1.12 → 1.1.13-beta.1
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 +12 -7
- package/.rush/temp/shrinkwrap-deps.json +155 -2
- package/dist/api/index.d.ts +1 -0
- package/dist/api/request.d.ts +7 -0
- package/dist/index.cjs.js +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.esm.js +1 -1
- package/dist/index.iife.js +1 -1
- package/dist/index.js +1519 -0
- package/dist/loader/__tests__/local-storage.test.d.ts +1 -0
- package/dist/loader/__tests__/localstorage-protector.d.ts +14 -0
- package/dist/loader/local-storage.d.ts +1 -0
- package/dist/sdks/lifecycle.d.ts +1 -0
- package/dist/sdks/router.d.ts +15 -0
- package/esbuild.config.js +26 -0
- package/package.json +7 -4
- package/sdk.build.log +4 -4
- package/src/api/index.ts +1 -0
- package/src/api/request.ts +15 -0
- package/src/index.ts +7 -2
- package/src/loader/__tests__/local-storage.test.ts +36 -0
- package/src/loader/__tests__/localstorage-protector.ts +191 -0
- package/src/loader/h5.ts +7 -2
- package/src/loader/local-storage.ts +33 -0
- package/src/sdks/lifecycle.ts +2 -2
- package/src/sdks/router.ts +30 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
type StorageIsolationOptions = {
|
|
2
|
+
namespace?: string;
|
|
3
|
+
debug?: boolean;
|
|
4
|
+
};
|
|
5
|
+
declare global {
|
|
6
|
+
interface Window {
|
|
7
|
+
__joliboxLocalStorage__: typeof window.localStorage;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export declare function createStorageIsolation(options?: StorageIsolationOptions): {
|
|
11
|
+
isolateFrame: (frame: HTMLIFrameElement) => void;
|
|
12
|
+
isolateWindowStorage: () => void;
|
|
13
|
+
};
|
|
14
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getOriginalLocalStorage(): Storage;
|
package/dist/sdks/lifecycle.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export declare class LifecycleSDK extends BaseSDK<LifecycleSDKEventMap> implemen
|
|
|
9
9
|
onReady(callback: (info?: Env['hostUserInfo']) => void): void;
|
|
10
10
|
exit(params: {
|
|
11
11
|
onBeforeExit: () => void;
|
|
12
|
+
shouldStay?: boolean;
|
|
12
13
|
}): {
|
|
13
14
|
code: import("@jolibox/types").ResponseType;
|
|
14
15
|
message: string;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { BaseSDK } from './sdk';
|
|
2
|
+
import { Router, ResponseType, StandardResponse } from '@jolibox/types';
|
|
3
|
+
export declare class RouterSDK extends BaseSDK implements Router {
|
|
4
|
+
openSchema(schema: string): Promise<{
|
|
5
|
+
code: ResponseType;
|
|
6
|
+
message: string;
|
|
7
|
+
}>;
|
|
8
|
+
openPage(url: string): Promise<StandardResponse<{
|
|
9
|
+
webviewId: number;
|
|
10
|
+
}>>;
|
|
11
|
+
closePage(webviewId: number): Promise<{
|
|
12
|
+
code: ResponseType;
|
|
13
|
+
message: string;
|
|
14
|
+
}>;
|
|
15
|
+
}
|
package/esbuild.config.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const esbuild = require('esbuild');
|
|
2
2
|
const fs = require('fs');
|
|
3
|
+
const babel = require('@babel/core');
|
|
3
4
|
|
|
4
5
|
function versionPlugin(version) {
|
|
5
6
|
return {
|
|
@@ -52,9 +53,34 @@ function build(format) {
|
|
|
52
53
|
'.js': 'jsx'
|
|
53
54
|
},
|
|
54
55
|
plugins: [versionPlugin(process.env.BUILD_VERSION || '1.0.0')],
|
|
56
|
+
inject: ['../../polyfills/abort-controller-polyfill.js'],
|
|
55
57
|
});
|
|
56
58
|
}
|
|
57
59
|
|
|
60
|
+
// Step 1: Bundle with esbuild
|
|
61
|
+
esbuild.buildSync({
|
|
62
|
+
entryPoints: ['src/index.js'],
|
|
63
|
+
bundle: true,
|
|
64
|
+
outfile: 'dist/temp.js',
|
|
65
|
+
format: 'iife',
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// Step 2: Transform with Babel
|
|
69
|
+
const code = fs.readFileSync('dist/temp.js', 'utf8');
|
|
70
|
+
const result = babel.transformSync(code, {
|
|
71
|
+
presets: [
|
|
72
|
+
['@babel/preset-env', {
|
|
73
|
+
targets: {
|
|
74
|
+
safari: '14'
|
|
75
|
+
}
|
|
76
|
+
}]
|
|
77
|
+
]
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// Write the final output
|
|
81
|
+
fs.writeFileSync('dist/index.js', result.code);
|
|
82
|
+
fs.unlinkSync('dist/temp.js'); // Clean up temp file
|
|
83
|
+
|
|
58
84
|
(async ()=>{
|
|
59
85
|
try{
|
|
60
86
|
await build(options.format);
|
package/package.json
CHANGED
|
@@ -1,21 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jolibox/sdk",
|
|
3
3
|
"description": "This project is common Jolibox JS-SDk interfere",
|
|
4
|
-
"version": "1.1.
|
|
4
|
+
"version": "1.1.13-beta.1",
|
|
5
5
|
"main": "dist/index.cjs.js",
|
|
6
6
|
"module": "dist/index.esm.js",
|
|
7
7
|
"typings": "dist/index.d.ts",
|
|
8
8
|
"license": "MIT",
|
|
9
9
|
"dependencies": {
|
|
10
|
-
"@jolibox/common": "1.1.
|
|
11
|
-
"@jolibox/types": "1.1.
|
|
10
|
+
"@jolibox/common": "1.1.13-beta.1",
|
|
11
|
+
"@jolibox/types": "1.1.13-beta.1"
|
|
12
12
|
},
|
|
13
13
|
"devDependencies": {
|
|
14
14
|
"typescript": "5.7.3",
|
|
15
15
|
"@jolibox/eslint-config": "1.0.0",
|
|
16
16
|
"@types/jest": "28.1.1",
|
|
17
17
|
"rimraf": "6.0.1",
|
|
18
|
-
"esbuild": "0.24.2"
|
|
18
|
+
"esbuild": "0.24.2",
|
|
19
|
+
"@babel/core": "7.23.3",
|
|
20
|
+
"@babel/preset-env": "7.23.3",
|
|
21
|
+
"@babel/preset-typescript": "7.23.3"
|
|
19
22
|
},
|
|
20
23
|
"scripts": {
|
|
21
24
|
"clean": "rimraf ./dist",
|
package/sdk.build.log
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
Invoking: npm run clean && npm run build:cjs && npm run build:esm && npm run build:iife && tsc
|
|
2
2
|
|
|
3
|
-
> @jolibox/sdk@1.1.
|
|
3
|
+
> @jolibox/sdk@1.1.13-beta.1 clean
|
|
4
4
|
> rimraf ./dist
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
> @jolibox/sdk@1.1.
|
|
7
|
+
> @jolibox/sdk@1.1.13-beta.1 build:cjs
|
|
8
8
|
> BUILD_VERSION=$(node -p "require('./package.json').version") node esbuild.config.js --format=cjs
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
> @jolibox/sdk@1.1.
|
|
11
|
+
> @jolibox/sdk@1.1.13-beta.1 build:esm
|
|
12
12
|
> BUILD_VERSION=$(node -p "require('./package.json').version") node esbuild.config.js --format=esm
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
> @jolibox/sdk@1.1.
|
|
15
|
+
> @jolibox/sdk@1.1.13-beta.1 build:iife
|
|
16
16
|
> BUILD_VERSION=$(node -p "require('./package.json').version") node esbuild.config.js --format=iife
|
|
17
17
|
|
package/src/api/index.ts
CHANGED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { RequestParams } from '@jolibox/types';
|
|
2
|
+
import { canIUse } from './can-i-use';
|
|
3
|
+
import { createCommands } from '@jolibox/common';
|
|
4
|
+
|
|
5
|
+
const commands = createCommands();
|
|
6
|
+
|
|
7
|
+
export async function request(params: RequestParams) {
|
|
8
|
+
if (!canIUse('request')) {
|
|
9
|
+
return {
|
|
10
|
+
code: 'FAILURE' as ResponseType,
|
|
11
|
+
message: '[Jolibox SDK]request is not supported in this platform'
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
return await commands.executeCommand('HttpSDK.request', params);
|
|
15
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -8,13 +8,14 @@ import './loader';
|
|
|
8
8
|
/**
|
|
9
9
|
* @public Jolibox JS SDK Entry
|
|
10
10
|
*/
|
|
11
|
-
import { getSystemInfoSync, canIUse, login, checkSession } from './api';
|
|
11
|
+
import { getSystemInfoSync, canIUse, login, checkSession, request } from './api';
|
|
12
12
|
import { RuntimeSDK } from './sdks/runtime';
|
|
13
13
|
import { LifecycleSDK } from './sdks/lifecycle';
|
|
14
14
|
import { StorageSDK } from './sdks/storage';
|
|
15
15
|
import { JoliboxAds } from './sdks/ads';
|
|
16
16
|
import { KeyboardSDK } from './sdks/keyboard';
|
|
17
17
|
import { TaskTrackerSDK } from './sdks/task';
|
|
18
|
+
import { RouterSDK } from './sdks/router';
|
|
18
19
|
|
|
19
20
|
declare global {
|
|
20
21
|
interface Window {
|
|
@@ -26,6 +27,7 @@ declare global {
|
|
|
26
27
|
storage: InstanceType<typeof StorageSDK>;
|
|
27
28
|
keyboard: InstanceType<typeof KeyboardSDK>;
|
|
28
29
|
task: InstanceType<typeof TaskTrackerSDK>;
|
|
30
|
+
router: InstanceType<typeof RouterSDK>;
|
|
29
31
|
};
|
|
30
32
|
}
|
|
31
33
|
}
|
|
@@ -38,12 +40,14 @@ export class JoliboxSDK {
|
|
|
38
40
|
readonly storage = new StorageSDK();
|
|
39
41
|
readonly keyboard = new KeyboardSDK();
|
|
40
42
|
readonly task = new TaskTrackerSDK();
|
|
43
|
+
readonly router = new RouterSDK();
|
|
41
44
|
|
|
42
45
|
//global API
|
|
43
46
|
getSystemInfoSync = getSystemInfoSync.bind(this);
|
|
44
47
|
canIUse = canIUse.bind(this);
|
|
45
48
|
login = login.bind(this);
|
|
46
49
|
checkSession = checkSession.bind(this);
|
|
50
|
+
request = request.bind(this);
|
|
47
51
|
|
|
48
52
|
constructor() {
|
|
49
53
|
window.joliboxsdk = {
|
|
@@ -52,7 +56,8 @@ export class JoliboxSDK {
|
|
|
52
56
|
lifecycle: this.lifecycle,
|
|
53
57
|
storage: this.storage,
|
|
54
58
|
keyboard: this.keyboard,
|
|
55
|
-
task: this.task
|
|
59
|
+
task: this.task,
|
|
60
|
+
router: this.router
|
|
56
61
|
};
|
|
57
62
|
}
|
|
58
63
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { createStorageIsolation } from './localstorage-protector';
|
|
2
|
+
import { getOriginalLocalStorage } from '../local-storage';
|
|
3
|
+
|
|
4
|
+
createStorageIsolation({
|
|
5
|
+
namespace: 'jolibox-sdk-test'
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
describe('getOriginalLocalStorage', () => {
|
|
9
|
+
it('should return localStorage object', () => {
|
|
10
|
+
const originalStorage = getOriginalLocalStorage();
|
|
11
|
+
|
|
12
|
+
expect(originalStorage).toBeDefined();
|
|
13
|
+
expect(typeof originalStorage.getItem).toBe('function');
|
|
14
|
+
expect(typeof originalStorage.setItem).toBe('function');
|
|
15
|
+
expect(typeof originalStorage.removeItem).toBe('function');
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('should be able to store and get data', () => {
|
|
19
|
+
const originalStorage = getOriginalLocalStorage();
|
|
20
|
+
const testKey = '__test_key__';
|
|
21
|
+
const testValue = 'test-value';
|
|
22
|
+
|
|
23
|
+
originalStorage.removeItem(testKey);
|
|
24
|
+
|
|
25
|
+
originalStorage.setItem(testKey, testValue);
|
|
26
|
+
|
|
27
|
+
// 验证数据是否正确存储
|
|
28
|
+
expect(originalStorage.getItem(testKey)).toBe(testValue);
|
|
29
|
+
expect(originalStorage.getItem('jolibox-sdk-test:__test_key__')).toBeNull();
|
|
30
|
+
|
|
31
|
+
// 清理测试数据
|
|
32
|
+
originalStorage.removeItem(testKey);
|
|
33
|
+
expect(originalStorage.getItem(testKey)).toBeNull();
|
|
34
|
+
expect(originalStorage.getItem('jolibox-sdk-test:__test_key__')).toBeNull();
|
|
35
|
+
});
|
|
36
|
+
});
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
type StorageIsolationOptions = {
|
|
2
|
+
namespace?: string;
|
|
3
|
+
debug?: boolean;
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
declare global {
|
|
7
|
+
interface Window {
|
|
8
|
+
__joliboxLocalStorage__: typeof window.localStorage;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function createStorageIsolation(options: StorageIsolationOptions = {}) {
|
|
13
|
+
const namespace = options.namespace || getJoliMpId();
|
|
14
|
+
const debug = options.debug || true;
|
|
15
|
+
const observedFrames = new WeakSet<HTMLIFrameElement>();
|
|
16
|
+
|
|
17
|
+
function getJoliMpId() {
|
|
18
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
19
|
+
return urlParams.get('mpId') ?? urlParams.get('appId') ?? urlParams.get('gameId') ?? '';
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function _log(message: string) {
|
|
23
|
+
if (debug) {
|
|
24
|
+
console.log(`[StorageIsolation] ${message}`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function createIsolatedStorage() {
|
|
29
|
+
const originalStorage = window.localStorage;
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
setItem(key: string, value: string) {
|
|
33
|
+
const namespacedKey = key.startsWith(`${namespace}:`) ? key : `${namespace}:${key}`;
|
|
34
|
+
originalStorage.setItem(namespacedKey, value);
|
|
35
|
+
},
|
|
36
|
+
getItem(key: string) {
|
|
37
|
+
const namespacedKey = key.startsWith(`${namespace}:`) ? key : `${namespace}:${key}`;
|
|
38
|
+
let value = originalStorage.getItem(namespacedKey);
|
|
39
|
+
if (value === null) {
|
|
40
|
+
// 如果命名空间不存在,则尝试直接获取原始键
|
|
41
|
+
const originalKey = key.startsWith(`${namespace}:`) ? key.slice(namespace.length + 1) : key;
|
|
42
|
+
value = originalStorage.getItem(originalKey);
|
|
43
|
+
}
|
|
44
|
+
return value;
|
|
45
|
+
},
|
|
46
|
+
removeItem(key: string) {
|
|
47
|
+
const namespacedKey = key.startsWith(`${namespace}:`) ? key : `${namespace}:${key}`;
|
|
48
|
+
originalStorage.removeItem(namespacedKey);
|
|
49
|
+
},
|
|
50
|
+
clear() {
|
|
51
|
+
const keys = Object.keys(originalStorage);
|
|
52
|
+
for (const key of keys) {
|
|
53
|
+
if (key.startsWith(`${namespace}:`)) {
|
|
54
|
+
originalStorage.removeItem(key);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
key(index: number) {
|
|
59
|
+
const keys = Object.keys(originalStorage)
|
|
60
|
+
.filter((key) => key.startsWith(`${namespace}:`))
|
|
61
|
+
.map((key) => key.slice(namespace.length + 1));
|
|
62
|
+
return keys[index] || null;
|
|
63
|
+
},
|
|
64
|
+
get length() {
|
|
65
|
+
return Object.keys(originalStorage).filter((key) => key.startsWith(`${namespace}:`)).length;
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function injectIsolatedStorage(
|
|
71
|
+
frameWindow: Window,
|
|
72
|
+
isolatedStorage: ReturnType<typeof createIsolatedStorage>
|
|
73
|
+
) {
|
|
74
|
+
try {
|
|
75
|
+
const originalStorage = frameWindow.localStorage;
|
|
76
|
+
window.__joliboxLocalStorage__ = originalStorage;
|
|
77
|
+
|
|
78
|
+
type StorageProp = keyof typeof isolatedStorage;
|
|
79
|
+
const storageProxy = new Proxy(originalStorage, {
|
|
80
|
+
get: (target, prop: StorageProp) => {
|
|
81
|
+
if (prop in isolatedStorage) {
|
|
82
|
+
return isolatedStorage[prop];
|
|
83
|
+
}
|
|
84
|
+
if (typeof target[prop] === 'function') {
|
|
85
|
+
return target[prop].bind(target);
|
|
86
|
+
}
|
|
87
|
+
return target[prop];
|
|
88
|
+
},
|
|
89
|
+
set: (target, prop: StorageProp, value) => {
|
|
90
|
+
if (prop === 'length') {
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
if (prop in isolatedStorage) {
|
|
94
|
+
isolatedStorage[prop] = value;
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
target[prop] = value;
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
Object.defineProperty(frameWindow, 'localStorage', {
|
|
103
|
+
get: () => storageProxy,
|
|
104
|
+
configurable: true
|
|
105
|
+
});
|
|
106
|
+
} catch (e) {
|
|
107
|
+
_log(`Failed to inject storage proxy: ${e}`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function injectIsolation(frame: HTMLIFrameElement) {
|
|
112
|
+
try {
|
|
113
|
+
const frameWindow = frame.contentWindow;
|
|
114
|
+
const frameDocument = frame.contentDocument;
|
|
115
|
+
|
|
116
|
+
if (!frameWindow || !frameDocument) {
|
|
117
|
+
_log('Cannot access frame content - likely due to same-origin policy');
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const isolatedStorage = createIsolatedStorage();
|
|
122
|
+
injectIsolatedStorage(frameWindow, isolatedStorage);
|
|
123
|
+
_log(`Successfully isolated storage for frame: ${frame.src}`);
|
|
124
|
+
} catch (e) {
|
|
125
|
+
_log(`Injection failed: ${e}`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function isolateFrame(frame: HTMLIFrameElement) {
|
|
130
|
+
if (observedFrames.has(frame)) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
try {
|
|
135
|
+
frame.addEventListener('load', () => {
|
|
136
|
+
injectIsolation(frame);
|
|
137
|
+
});
|
|
138
|
+
if (frame.contentDocument && frame.contentDocument.readyState === 'complete') {
|
|
139
|
+
injectIsolation(frame);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
observedFrames.add(frame);
|
|
143
|
+
} catch (e) {
|
|
144
|
+
_log(`Failed to isolate frame: ${e}`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function handleExistingFrames() {
|
|
149
|
+
document.querySelectorAll('iframe').forEach((frame) => {
|
|
150
|
+
injectIsolation(frame);
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function startObserving() {
|
|
155
|
+
handleExistingFrames();
|
|
156
|
+
|
|
157
|
+
const observer = new MutationObserver((mutations) => {
|
|
158
|
+
mutations.forEach((mutation) => {
|
|
159
|
+
mutation.addedNodes.forEach((node) => {
|
|
160
|
+
if (node instanceof HTMLIFrameElement) {
|
|
161
|
+
isolateFrame(node);
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
observer.observe(document.documentElement, {
|
|
168
|
+
childList: true,
|
|
169
|
+
subtree: true
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
_log('Started observing iframe creation');
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function isolateWindowStorage() {
|
|
176
|
+
const isolatedStorage = createIsolatedStorage();
|
|
177
|
+
injectIsolatedStorage(window, isolatedStorage);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Initialize
|
|
181
|
+
startObserving();
|
|
182
|
+
isolateWindowStorage();
|
|
183
|
+
|
|
184
|
+
// Return public API if needed
|
|
185
|
+
return {
|
|
186
|
+
isolateFrame,
|
|
187
|
+
isolateWindowStorage
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
createStorageIsolation();
|
package/src/loader/h5.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { getBoostrapModuleUrl, getImplementModuleUrl } from './index';
|
|
|
5
5
|
import { timeline } from '../events';
|
|
6
6
|
import { testMode } from '@/utils/env';
|
|
7
7
|
import { trackError } from '@/utils/event-tracker';
|
|
8
|
+
import { getOriginalLocalStorage } from './local-storage';
|
|
8
9
|
|
|
9
10
|
const LOCAL_STORE_KEY = 'jolibox-sdk-loadermeta';
|
|
10
11
|
interface LocalStoreMeta {
|
|
@@ -16,7 +17,11 @@ interface LocalStoreMeta {
|
|
|
16
17
|
timestamp?: number;
|
|
17
18
|
}
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
getOriginalLocalStorage();
|
|
21
|
+
|
|
22
|
+
const CURRENT_VERSION_STORE: LocalStoreMeta = JSON.parse(
|
|
23
|
+
window.__joliboxLocalStorage__.getItem(LOCAL_STORE_KEY) ?? '{}'
|
|
24
|
+
);
|
|
20
25
|
const now = Date.now();
|
|
21
26
|
|
|
22
27
|
const expired = (now: number, prev: number) =>
|
|
@@ -67,7 +72,7 @@ async function fetchCurrentRemoteScript() {
|
|
|
67
72
|
}
|
|
68
73
|
}
|
|
69
74
|
|
|
70
|
-
|
|
75
|
+
window.__joliboxLocalStorage__.setItem(LOCAL_STORE_KEY, JSON.stringify(currentStore));
|
|
71
76
|
} catch (error) {
|
|
72
77
|
console.warn('Failed to fetch loader metadata: ', error);
|
|
73
78
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export function getOriginalLocalStorage(): Storage {
|
|
2
|
+
try {
|
|
3
|
+
if (window.__joliboxLocalStorage__) {
|
|
4
|
+
return window.__joliboxLocalStorage__;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
let originalDescriptor = Object.getOwnPropertyDescriptor(window, 'localStorage');
|
|
8
|
+
if (originalDescriptor && originalDescriptor.get) {
|
|
9
|
+
const originalLocalStorage = originalDescriptor.get.call(window);
|
|
10
|
+
window.__joliboxLocalStorage__ = originalLocalStorage;
|
|
11
|
+
return originalLocalStorage;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
originalDescriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(window), 'localStorage');
|
|
15
|
+
if (originalDescriptor && originalDescriptor.get) {
|
|
16
|
+
const originalLocalStorage = originalDescriptor.get.call(window);
|
|
17
|
+
return originalLocalStorage;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const windowProto = Window.prototype;
|
|
21
|
+
const protoDescriptor = Object.getOwnPropertyDescriptor(windowProto, 'localStorage');
|
|
22
|
+
if (protoDescriptor && protoDescriptor.get) {
|
|
23
|
+
const protoLocalStorage = protoDescriptor.get.call(window);
|
|
24
|
+
window.__joliboxLocalStorage__ = protoLocalStorage;
|
|
25
|
+
return protoLocalStorage;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return localStorage;
|
|
29
|
+
} catch (e) {
|
|
30
|
+
console.warn('Failed to get original localStorage, fallback to default implementation', e);
|
|
31
|
+
return localStorage;
|
|
32
|
+
}
|
|
33
|
+
}
|
package/src/sdks/lifecycle.ts
CHANGED
|
@@ -19,12 +19,12 @@ export class LifecycleSDK extends BaseSDK<LifecycleSDKEventMap> implements Lifec
|
|
|
19
19
|
this.commands.executeCommand('LifecycleSDK.onReady', wrappedOnReady.bind(this));
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
exit(params: { onBeforeExit: () => void }) {
|
|
22
|
+
exit(params: { onBeforeExit: () => void; shouldStay?: boolean }) {
|
|
23
23
|
const errMsg = this.canIUseIfThrow('lifeCycle.exit');
|
|
24
24
|
if (errMsg) {
|
|
25
25
|
return errMsg;
|
|
26
26
|
}
|
|
27
|
-
this.commands.executeCommand('LifecycleSDK.exit', params.onBeforeExit);
|
|
27
|
+
this.commands.executeCommand('LifecycleSDK.exit', params.onBeforeExit, params.shouldStay);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
onJoliboxHide(params: () => void) {
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { BaseSDK } from './sdk';
|
|
2
|
+
import { Router, ResponseType, StandardResponse } from '@jolibox/types';
|
|
3
|
+
|
|
4
|
+
export class RouterSDK extends BaseSDK implements Router {
|
|
5
|
+
async openSchema(schema: string) {
|
|
6
|
+
const errMsg = this.canIUseIfThrow('router.openSchema');
|
|
7
|
+
if (errMsg) {
|
|
8
|
+
return errMsg;
|
|
9
|
+
}
|
|
10
|
+
return await this.commands.executeCommand('RouterSDK.openSchema', schema);
|
|
11
|
+
}
|
|
12
|
+
async openPage(url: string): Promise<
|
|
13
|
+
StandardResponse<{
|
|
14
|
+
webviewId: number;
|
|
15
|
+
}>
|
|
16
|
+
> {
|
|
17
|
+
const errMsg = this.canIUseIfThrow('router.openPage');
|
|
18
|
+
if (errMsg) {
|
|
19
|
+
return errMsg;
|
|
20
|
+
}
|
|
21
|
+
return await this.commands.executeCommand('RouterSDK.openPage', url);
|
|
22
|
+
}
|
|
23
|
+
async closePage(webviewId: number) {
|
|
24
|
+
const errMsg = this.canIUseIfThrow('router.closePage');
|
|
25
|
+
if (errMsg) {
|
|
26
|
+
return errMsg;
|
|
27
|
+
}
|
|
28
|
+
return await this.commands.executeCommand('RouterSDK.closePage', webviewId);
|
|
29
|
+
}
|
|
30
|
+
}
|