even-toolkit 1.5.9 → 1.6.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/dist/glasses/storage.d.ts +14 -43
- package/dist/glasses/storage.d.ts.map +1 -1
- package/dist/glasses/storage.js +54 -71
- package/dist/glasses/storage.js.map +1 -1
- package/glasses/storage.ts +41 -75
- package/package.json +1 -1
|
@@ -1,48 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Persistent storage for Even Hub apps.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* Usage:
|
|
9
|
-
* import { storageSet, storageGetSync, hydrateFromSDK } from 'even-toolkit/storage';
|
|
10
|
-
*
|
|
11
|
-
* // In main.tsx — hydrate before render:
|
|
12
|
-
* hydrateFromSDK(['my-app:settings', 'my-app:data']).finally(() => {
|
|
13
|
-
* createRoot(...).render(<App />);
|
|
14
|
-
* });
|
|
15
|
-
*
|
|
16
|
-
* // Read (synchronous):
|
|
17
|
-
* const data = storageGetSync<MyData>('my-app:data', defaultValue);
|
|
18
|
-
*
|
|
19
|
-
* // Write (dual-write to localStorage + SDK bridge):
|
|
20
|
-
* storageSet('my-app:data', data);
|
|
21
|
-
*/
|
|
22
|
-
/**
|
|
23
|
-
* Read a JSON value synchronously from browser localStorage.
|
|
24
|
-
* Call `hydrateFromSDK()` at startup to ensure localStorage has the latest SDK data.
|
|
25
|
-
*/
|
|
26
|
-
export declare function storageGetSync<T>(key: string, fallback: T): T;
|
|
27
|
-
/**
|
|
28
|
-
* Write a JSON-serializable value to both localStorage and SDK bridge.
|
|
29
|
-
*/
|
|
30
|
-
export declare function storageSet(key: string, value: unknown): void;
|
|
31
|
-
/**
|
|
32
|
-
* Write a raw string value to both localStorage and SDK bridge.
|
|
33
|
-
* Use for pre-serialized or encrypted values that shouldn't be double-stringified.
|
|
34
|
-
*/
|
|
35
|
-
export declare function storageSetRaw(key: string, value: string): void;
|
|
36
|
-
/**
|
|
37
|
-
* Remove a key from both localStorage and SDK bridge.
|
|
38
|
-
*/
|
|
39
|
-
export declare function storageRemove(key: string): void;
|
|
40
|
-
/**
|
|
41
|
-
* Hydrate browser localStorage from SDK bridge on app startup.
|
|
42
|
-
* Call once before React renders so `storageGetSync` reads fresh data.
|
|
43
|
-
* Gets the raw SDK bridge directly (doesn't depend on useGlasses).
|
|
44
|
-
*
|
|
45
|
-
* @param keys - All storage keys used by the app
|
|
4
|
+
* Writes to BOTH the SDK bridge AND browser localStorage.
|
|
5
|
+
* Reads from SDK bridge first, falls back to localStorage.
|
|
6
|
+
* This ensures persistence on the real Even Hub (bridge)
|
|
7
|
+
* and in development/simulator (localStorage).
|
|
46
8
|
*/
|
|
47
|
-
|
|
9
|
+
/** Read a JSON value — tries SDK bridge first, then localStorage */
|
|
10
|
+
export declare function storageGet<T>(key: string, fallback: T): Promise<T>;
|
|
11
|
+
/** Read a raw string — tries SDK bridge first, then localStorage */
|
|
12
|
+
export declare function storageGetRaw(key: string): Promise<string>;
|
|
13
|
+
/** Write a JSON value to BOTH SDK bridge and localStorage */
|
|
14
|
+
export declare function storageSet(key: string, value: unknown): Promise<void>;
|
|
15
|
+
/** Write a raw string to BOTH SDK bridge and localStorage */
|
|
16
|
+
export declare function storageSetRaw(key: string, value: string): Promise<void>;
|
|
17
|
+
/** Remove a key from BOTH SDK bridge and localStorage */
|
|
18
|
+
export declare function storageRemove(key: string): Promise<void>;
|
|
48
19
|
//# sourceMappingURL=storage.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../glasses/storage.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../glasses/storage.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAwBH,oEAAoE;AACpE,wBAAsB,UAAU,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAaxE;AAED,oEAAoE;AACpE,wBAAsB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAahE;AAED,6DAA6D;AAC7D,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAO3E;AAED,6DAA6D;AAC7D,wBAAsB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAM7E;AAED,yDAAyD;AACzD,wBAAsB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAM9D"}
|
package/dist/glasses/storage.js
CHANGED
|
@@ -1,53 +1,28 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Persistent storage for Even Hub apps.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* Usage:
|
|
9
|
-
* import { storageSet, storageGetSync, hydrateFromSDK } from 'even-toolkit/storage';
|
|
10
|
-
*
|
|
11
|
-
* // In main.tsx — hydrate before render:
|
|
12
|
-
* hydrateFromSDK(['my-app:settings', 'my-app:data']).finally(() => {
|
|
13
|
-
* createRoot(...).render(<App />);
|
|
14
|
-
* });
|
|
15
|
-
*
|
|
16
|
-
* // Read (synchronous):
|
|
17
|
-
* const data = storageGetSync<MyData>('my-app:data', defaultValue);
|
|
18
|
-
*
|
|
19
|
-
* // Write (dual-write to localStorage + SDK bridge):
|
|
20
|
-
* storageSet('my-app:data', data);
|
|
21
|
-
*/
|
|
22
|
-
/**
|
|
23
|
-
* Get a bridge object that has setLocalStorage/getLocalStorage.
|
|
24
|
-
* Checks window.__evenBridge (our wrapper) first,
|
|
25
|
-
* then tries the raw SDK bridge directly via waitForEvenAppBridge.
|
|
4
|
+
* Writes to BOTH the SDK bridge AND browser localStorage.
|
|
5
|
+
* Reads from SDK bridge first, falls back to localStorage.
|
|
6
|
+
* This ensures persistence on the real Even Hub (bridge)
|
|
7
|
+
* and in development/simulator (localStorage).
|
|
26
8
|
*/
|
|
27
9
|
function getBridge() {
|
|
28
10
|
const bridge = window.__evenBridge;
|
|
29
11
|
if (bridge?.setLocalStorage)
|
|
30
12
|
return bridge;
|
|
31
|
-
// Also check raw bridge exposed on the wrapper
|
|
32
13
|
if (bridge?.rawBridge?.setLocalStorage)
|
|
33
14
|
return bridge.rawBridge;
|
|
34
15
|
return null;
|
|
35
16
|
}
|
|
36
|
-
|
|
37
|
-
* Try to get a raw SDK bridge for hydration (before useGlasses sets window.__evenBridge).
|
|
38
|
-
* Returns null if SDK is not available (web/dev environment).
|
|
39
|
-
*/
|
|
40
|
-
async function getRawBridgeForHydration() {
|
|
41
|
-
// If our wrapper is already set, use it
|
|
17
|
+
async function getRawBridge() {
|
|
42
18
|
const existing = getBridge();
|
|
43
19
|
if (existing)
|
|
44
20
|
return existing;
|
|
45
|
-
// Try to get raw bridge directly from the SDK
|
|
46
21
|
try {
|
|
47
22
|
const { EvenBetterSdk } = await import('@jappyjan/even-better-sdk');
|
|
48
23
|
const raw = await Promise.race([
|
|
49
24
|
EvenBetterSdk.getRawBridge(),
|
|
50
|
-
new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')),
|
|
25
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), 3000)),
|
|
51
26
|
]);
|
|
52
27
|
return raw;
|
|
53
28
|
}
|
|
@@ -55,11 +30,17 @@ async function getRawBridgeForHydration() {
|
|
|
55
30
|
return null;
|
|
56
31
|
}
|
|
57
32
|
}
|
|
58
|
-
/**
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
33
|
+
/** Read a JSON value — tries SDK bridge first, then localStorage */
|
|
34
|
+
export async function storageGet(key, fallback) {
|
|
35
|
+
const bridge = getBridge() ?? await getRawBridge();
|
|
36
|
+
if (bridge?.getLocalStorage) {
|
|
37
|
+
try {
|
|
38
|
+
const raw = await bridge.getLocalStorage(key);
|
|
39
|
+
if (raw && raw !== '')
|
|
40
|
+
return JSON.parse(raw);
|
|
41
|
+
}
|
|
42
|
+
catch { /* fall through */ }
|
|
43
|
+
}
|
|
63
44
|
try {
|
|
64
45
|
const raw = localStorage.getItem(key);
|
|
65
46
|
if (raw)
|
|
@@ -68,10 +49,26 @@ export function storageGetSync(key, fallback) {
|
|
|
68
49
|
catch { /* ignore */ }
|
|
69
50
|
return fallback;
|
|
70
51
|
}
|
|
71
|
-
/**
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
52
|
+
/** Read a raw string — tries SDK bridge first, then localStorage */
|
|
53
|
+
export async function storageGetRaw(key) {
|
|
54
|
+
const bridge = getBridge() ?? await getRawBridge();
|
|
55
|
+
if (bridge?.getLocalStorage) {
|
|
56
|
+
try {
|
|
57
|
+
const val = await bridge.getLocalStorage(key);
|
|
58
|
+
if (val && val !== '')
|
|
59
|
+
return val;
|
|
60
|
+
}
|
|
61
|
+
catch { /* fall through */ }
|
|
62
|
+
}
|
|
63
|
+
try {
|
|
64
|
+
return localStorage.getItem(key) ?? '';
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return '';
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/** Write a JSON value to BOTH SDK bridge and localStorage */
|
|
71
|
+
export async function storageSet(key, value) {
|
|
75
72
|
const json = JSON.stringify(value);
|
|
76
73
|
try {
|
|
77
74
|
localStorage.setItem(key, json);
|
|
@@ -79,50 +76,36 @@ export function storageSet(key, value) {
|
|
|
79
76
|
catch { /* ignore */ }
|
|
80
77
|
const bridge = getBridge();
|
|
81
78
|
if (bridge?.setLocalStorage) {
|
|
82
|
-
|
|
79
|
+
try {
|
|
80
|
+
await bridge.setLocalStorage(key, json);
|
|
81
|
+
}
|
|
82
|
+
catch { /* ignore */ }
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
|
-
/**
|
|
86
|
-
|
|
87
|
-
* Use for pre-serialized or encrypted values that shouldn't be double-stringified.
|
|
88
|
-
*/
|
|
89
|
-
export function storageSetRaw(key, value) {
|
|
85
|
+
/** Write a raw string to BOTH SDK bridge and localStorage */
|
|
86
|
+
export async function storageSetRaw(key, value) {
|
|
90
87
|
try {
|
|
91
88
|
localStorage.setItem(key, value);
|
|
92
89
|
}
|
|
93
90
|
catch { /* ignore */ }
|
|
94
91
|
const bridge = getBridge();
|
|
95
92
|
if (bridge?.setLocalStorage) {
|
|
96
|
-
|
|
93
|
+
try {
|
|
94
|
+
await bridge.setLocalStorage(key, value);
|
|
95
|
+
}
|
|
96
|
+
catch { /* ignore */ }
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
|
-
/**
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
99
|
+
/** Remove a key from BOTH SDK bridge and localStorage */
|
|
100
|
+
export async function storageRemove(key) {
|
|
101
|
+
try {
|
|
102
|
+
localStorage.removeItem(key);
|
|
103
|
+
}
|
|
104
|
+
catch { /* ignore */ }
|
|
104
105
|
const bridge = getBridge();
|
|
105
106
|
if (bridge?.setLocalStorage) {
|
|
106
|
-
bridge.setLocalStorage(key, '').catch(() => { });
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
/**
|
|
110
|
-
* Hydrate browser localStorage from SDK bridge on app startup.
|
|
111
|
-
* Call once before React renders so `storageGetSync` reads fresh data.
|
|
112
|
-
* Gets the raw SDK bridge directly (doesn't depend on useGlasses).
|
|
113
|
-
*
|
|
114
|
-
* @param keys - All storage keys used by the app
|
|
115
|
-
*/
|
|
116
|
-
export async function hydrateFromSDK(keys) {
|
|
117
|
-
const bridge = await getRawBridgeForHydration();
|
|
118
|
-
if (!bridge?.getLocalStorage)
|
|
119
|
-
return;
|
|
120
|
-
for (const key of keys) {
|
|
121
107
|
try {
|
|
122
|
-
|
|
123
|
-
if (value && value !== '') {
|
|
124
|
-
localStorage.setItem(key, value);
|
|
125
|
-
}
|
|
108
|
+
await bridge.setLocalStorage(key, '');
|
|
126
109
|
}
|
|
127
110
|
catch { /* ignore */ }
|
|
128
111
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../glasses/storage.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../glasses/storage.ts"],"names":[],"mappings":"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"}
|
package/glasses/storage.ts
CHANGED
|
@@ -1,53 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Persistent storage for Even Hub apps.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* Usage:
|
|
9
|
-
* import { storageSet, storageGetSync, hydrateFromSDK } from 'even-toolkit/storage';
|
|
10
|
-
*
|
|
11
|
-
* // In main.tsx — hydrate before render:
|
|
12
|
-
* hydrateFromSDK(['my-app:settings', 'my-app:data']).finally(() => {
|
|
13
|
-
* createRoot(...).render(<App />);
|
|
14
|
-
* });
|
|
15
|
-
*
|
|
16
|
-
* // Read (synchronous):
|
|
17
|
-
* const data = storageGetSync<MyData>('my-app:data', defaultValue);
|
|
18
|
-
*
|
|
19
|
-
* // Write (dual-write to localStorage + SDK bridge):
|
|
20
|
-
* storageSet('my-app:data', data);
|
|
4
|
+
* Writes to BOTH the SDK bridge AND browser localStorage.
|
|
5
|
+
* Reads from SDK bridge first, falls back to localStorage.
|
|
6
|
+
* This ensures persistence on the real Even Hub (bridge)
|
|
7
|
+
* and in development/simulator (localStorage).
|
|
21
8
|
*/
|
|
22
9
|
|
|
23
|
-
/**
|
|
24
|
-
* Get a bridge object that has setLocalStorage/getLocalStorage.
|
|
25
|
-
* Checks window.__evenBridge (our wrapper) first,
|
|
26
|
-
* then tries the raw SDK bridge directly via waitForEvenAppBridge.
|
|
27
|
-
*/
|
|
28
10
|
function getBridge(): any {
|
|
29
11
|
const bridge = (window as any).__evenBridge;
|
|
30
12
|
if (bridge?.setLocalStorage) return bridge;
|
|
31
|
-
// Also check raw bridge exposed on the wrapper
|
|
32
13
|
if (bridge?.rawBridge?.setLocalStorage) return bridge.rawBridge;
|
|
33
14
|
return null;
|
|
34
15
|
}
|
|
35
16
|
|
|
36
|
-
|
|
37
|
-
* Try to get a raw SDK bridge for hydration (before useGlasses sets window.__evenBridge).
|
|
38
|
-
* Returns null if SDK is not available (web/dev environment).
|
|
39
|
-
*/
|
|
40
|
-
async function getRawBridgeForHydration(): Promise<any> {
|
|
41
|
-
// If our wrapper is already set, use it
|
|
17
|
+
async function getRawBridge(): Promise<any> {
|
|
42
18
|
const existing = getBridge();
|
|
43
19
|
if (existing) return existing;
|
|
44
|
-
|
|
45
|
-
// Try to get raw bridge directly from the SDK
|
|
46
20
|
try {
|
|
47
21
|
const { EvenBetterSdk } = await import('@jappyjan/even-better-sdk');
|
|
48
22
|
const raw = await Promise.race([
|
|
49
23
|
EvenBetterSdk.getRawBridge(),
|
|
50
|
-
new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')),
|
|
24
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), 3000)),
|
|
51
25
|
]);
|
|
52
26
|
return raw;
|
|
53
27
|
} catch {
|
|
@@ -55,11 +29,15 @@ async function getRawBridgeForHydration(): Promise<any> {
|
|
|
55
29
|
}
|
|
56
30
|
}
|
|
57
31
|
|
|
58
|
-
/**
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
32
|
+
/** Read a JSON value — tries SDK bridge first, then localStorage */
|
|
33
|
+
export async function storageGet<T>(key: string, fallback: T): Promise<T> {
|
|
34
|
+
const bridge = getBridge() ?? await getRawBridge();
|
|
35
|
+
if (bridge?.getLocalStorage) {
|
|
36
|
+
try {
|
|
37
|
+
const raw = await bridge.getLocalStorage(key);
|
|
38
|
+
if (raw && raw !== '') return JSON.parse(raw);
|
|
39
|
+
} catch { /* fall through */ }
|
|
40
|
+
}
|
|
63
41
|
try {
|
|
64
42
|
const raw = localStorage.getItem(key);
|
|
65
43
|
if (raw) return JSON.parse(raw);
|
|
@@ -67,58 +45,46 @@ export function storageGetSync<T>(key: string, fallback: T): T {
|
|
|
67
45
|
return fallback;
|
|
68
46
|
}
|
|
69
47
|
|
|
70
|
-
/**
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
48
|
+
/** Read a raw string — tries SDK bridge first, then localStorage */
|
|
49
|
+
export async function storageGetRaw(key: string): Promise<string> {
|
|
50
|
+
const bridge = getBridge() ?? await getRawBridge();
|
|
51
|
+
if (bridge?.getLocalStorage) {
|
|
52
|
+
try {
|
|
53
|
+
const val = await bridge.getLocalStorage(key);
|
|
54
|
+
if (val && val !== '') return val;
|
|
55
|
+
} catch { /* fall through */ }
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
return localStorage.getItem(key) ?? '';
|
|
59
|
+
} catch {
|
|
60
|
+
return '';
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** Write a JSON value to BOTH SDK bridge and localStorage */
|
|
65
|
+
export async function storageSet(key: string, value: unknown): Promise<void> {
|
|
74
66
|
const json = JSON.stringify(value);
|
|
75
67
|
try { localStorage.setItem(key, json); } catch { /* ignore */ }
|
|
76
68
|
const bridge = getBridge();
|
|
77
69
|
if (bridge?.setLocalStorage) {
|
|
78
|
-
bridge.setLocalStorage(key, json)
|
|
70
|
+
try { await bridge.setLocalStorage(key, json); } catch { /* ignore */ }
|
|
79
71
|
}
|
|
80
72
|
}
|
|
81
73
|
|
|
82
|
-
/**
|
|
83
|
-
|
|
84
|
-
* Use for pre-serialized or encrypted values that shouldn't be double-stringified.
|
|
85
|
-
*/
|
|
86
|
-
export function storageSetRaw(key: string, value: string): void {
|
|
74
|
+
/** Write a raw string to BOTH SDK bridge and localStorage */
|
|
75
|
+
export async function storageSetRaw(key: string, value: string): Promise<void> {
|
|
87
76
|
try { localStorage.setItem(key, value); } catch { /* ignore */ }
|
|
88
77
|
const bridge = getBridge();
|
|
89
78
|
if (bridge?.setLocalStorage) {
|
|
90
|
-
bridge.setLocalStorage(key, value)
|
|
79
|
+
try { await bridge.setLocalStorage(key, value); } catch { /* ignore */ }
|
|
91
80
|
}
|
|
92
81
|
}
|
|
93
82
|
|
|
94
|
-
/**
|
|
95
|
-
|
|
96
|
-
*/
|
|
97
|
-
export function storageRemove(key: string): void {
|
|
98
|
-
localStorage.removeItem(key);
|
|
83
|
+
/** Remove a key from BOTH SDK bridge and localStorage */
|
|
84
|
+
export async function storageRemove(key: string): Promise<void> {
|
|
85
|
+
try { localStorage.removeItem(key); } catch { /* ignore */ }
|
|
99
86
|
const bridge = getBridge();
|
|
100
87
|
if (bridge?.setLocalStorage) {
|
|
101
|
-
bridge.setLocalStorage(key, '')
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Hydrate browser localStorage from SDK bridge on app startup.
|
|
107
|
-
* Call once before React renders so `storageGetSync` reads fresh data.
|
|
108
|
-
* Gets the raw SDK bridge directly (doesn't depend on useGlasses).
|
|
109
|
-
*
|
|
110
|
-
* @param keys - All storage keys used by the app
|
|
111
|
-
*/
|
|
112
|
-
export async function hydrateFromSDK(keys: string[]): Promise<void> {
|
|
113
|
-
const bridge = await getRawBridgeForHydration();
|
|
114
|
-
if (!bridge?.getLocalStorage) return;
|
|
115
|
-
|
|
116
|
-
for (const key of keys) {
|
|
117
|
-
try {
|
|
118
|
-
const value = await bridge.getLocalStorage(key);
|
|
119
|
-
if (value && value !== '') {
|
|
120
|
-
localStorage.setItem(key, value);
|
|
121
|
-
}
|
|
122
|
-
} catch { /* ignore */ }
|
|
88
|
+
try { await bridge.setLocalStorage(key, ''); } catch { /* ignore */ }
|
|
123
89
|
}
|
|
124
90
|
}
|