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.
@@ -1,48 +1,19 @@
1
1
  /**
2
2
  * Persistent storage for Even Hub apps.
3
3
  *
4
- * The Even Hub WebView doesn't persist browser localStorage across app restarts.
5
- * This module uses the SDK's `bridge.setLocalStorage/getLocalStorage` which DO persist,
6
- * with browser localStorage as a sync-read cache and fallback for web/dev.
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
- export declare function hydrateFromSDK(keys: string[]): Promise<void>;
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;;;;;;;;;;;;;;;;;;;;GAoBG;AAqCH;;;GAGG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,CAAC,CAM7D;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAO5D;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAM9D;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAM/C;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAYlE"}
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"}
@@ -1,53 +1,28 @@
1
1
  /**
2
2
  * Persistent storage for Even Hub apps.
3
3
  *
4
- * The Even Hub WebView doesn't persist browser localStorage across app restarts.
5
- * This module uses the SDK's `bridge.setLocalStorage/getLocalStorage` which DO persist,
6
- * with browser localStorage as a sync-read cache and fallback for web/dev.
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')), 2000)),
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
- * Read a JSON value synchronously from browser localStorage.
60
- * Call `hydrateFromSDK()` at startup to ensure localStorage has the latest SDK data.
61
- */
62
- export function storageGetSync(key, fallback) {
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
- * Write a JSON-serializable value to both localStorage and SDK bridge.
73
- */
74
- export function storageSet(key, value) {
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
- bridge.setLocalStorage(key, json).catch(() => { });
79
+ try {
80
+ await bridge.setLocalStorage(key, json);
81
+ }
82
+ catch { /* ignore */ }
83
83
  }
84
84
  }
85
- /**
86
- * Write a raw string value to both localStorage and SDK bridge.
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
- bridge.setLocalStorage(key, value).catch(() => { });
93
+ try {
94
+ await bridge.setLocalStorage(key, value);
95
+ }
96
+ catch { /* ignore */ }
97
97
  }
98
98
  }
99
- /**
100
- * Remove a key from both localStorage and SDK bridge.
101
- */
102
- export function storageRemove(key) {
103
- localStorage.removeItem(key);
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
- const value = await bridge.getLocalStorage(key);
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":"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"}
1
+ {"version":3,"file":"storage.js","sourceRoot":"","sources":["../../glasses/storage.ts"],"names":[],"mappings":"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"}
@@ -1,53 +1,27 @@
1
1
  /**
2
2
  * Persistent storage for Even Hub apps.
3
3
  *
4
- * The Even Hub WebView doesn't persist browser localStorage across app restarts.
5
- * This module uses the SDK's `bridge.setLocalStorage/getLocalStorage` which DO persist,
6
- * with browser localStorage as a sync-read cache and fallback for web/dev.
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')), 2000)),
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
- * Read a JSON value synchronously from browser localStorage.
60
- * Call `hydrateFromSDK()` at startup to ensure localStorage has the latest SDK data.
61
- */
62
- export function storageGetSync<T>(key: string, fallback: T): T {
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
- * Write a JSON-serializable value to both localStorage and SDK bridge.
72
- */
73
- export function storageSet(key: string, value: unknown): void {
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).catch(() => {});
70
+ try { await bridge.setLocalStorage(key, json); } catch { /* ignore */ }
79
71
  }
80
72
  }
81
73
 
82
- /**
83
- * Write a raw string value to both localStorage and SDK bridge.
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).catch(() => {});
79
+ try { await bridge.setLocalStorage(key, value); } catch { /* ignore */ }
91
80
  }
92
81
  }
93
82
 
94
- /**
95
- * Remove a key from both localStorage and SDK bridge.
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, '').catch(() => {});
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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "even-toolkit",
3
- "version": "1.5.9",
3
+ "version": "1.6.1",
4
4
  "bin": {
5
5
  "even-toolkit": "./bin/create.js"
6
6
  },