@entropy-softworks/ui 2026.8.32 → 2026.8.33
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/lib/utils/index.d.ts +1 -1
- package/lib/utils/index.d.ts.map +1 -1
- package/lib/utils/index.js +1 -1
- package/lib/utils/index.js.map +1 -1
- package/lib/utils/settings-storage.d.ts +9 -0
- package/lib/utils/settings-storage.d.ts.map +1 -1
- package/lib/utils/settings-storage.js +45 -0
- package/lib/utils/settings-storage.js.map +1 -1
- package/package.json +1 -1
- package/src/utils/__tests__/settings-storage.test.ts +23 -1
- package/src/utils/index.ts +1 -1
- package/src/utils/settings-storage.ts +46 -0
package/lib/utils/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export { cn } from "./cn";
|
|
|
3
3
|
export { getErrorMessage } from "./error";
|
|
4
4
|
export { darkPalette, getPalette, lightPalette, usePalette, type ColorScheme, type Palette, } from "./palette";
|
|
5
5
|
export { clearClipboardNow, copyToClipboard } from "./clipboard";
|
|
6
|
-
export { loadSetting, saveSetting } from "./settings-storage";
|
|
6
|
+
export { loadSetting, saveSetting, loadJsonSetting, saveJsonSetting } from "./settings-storage";
|
|
7
7
|
export { debounce } from "./debounce";
|
|
8
8
|
export { ApiError, extractApiError, extractErrorMessage } from "./http-error";
|
|
9
9
|
export { generatePassword, type GeneratePasswordOptions } from "./password";
|
package/lib/utils/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,EAAE,EAAE,MAAM,MAAM,CAAC;AAC1B,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EACL,WAAW,EACX,UAAU,EACV,YAAY,EACZ,UAAU,EACV,KAAK,WAAW,EAChB,KAAK,OAAO,GACb,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,EAAE,EAAE,MAAM,MAAM,CAAC;AAC1B,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EACL,WAAW,EACX,UAAU,EACV,YAAY,EACZ,UAAU,EACV,KAAK,WAAW,EAChB,KAAK,OAAO,GACb,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAChG,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAC9E,OAAO,EAAE,gBAAgB,EAAE,KAAK,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAC5E,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,gBAAgB,EAChB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,GACxB,MAAM,cAAc,CAAC"}
|
package/lib/utils/index.js
CHANGED
|
@@ -3,7 +3,7 @@ export { cn } from "./cn";
|
|
|
3
3
|
export { getErrorMessage } from "./error";
|
|
4
4
|
export { darkPalette, getPalette, lightPalette, usePalette, } from "./palette";
|
|
5
5
|
export { clearClipboardNow, copyToClipboard } from "./clipboard";
|
|
6
|
-
export { loadSetting, saveSetting } from "./settings-storage";
|
|
6
|
+
export { loadSetting, saveSetting, loadJsonSetting, saveJsonSetting } from "./settings-storage";
|
|
7
7
|
export { debounce } from "./debounce";
|
|
8
8
|
export { ApiError, extractApiError, extractErrorMessage } from "./http-error";
|
|
9
9
|
export { generatePassword } from "./password";
|
package/lib/utils/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,EAAE,EAAE,MAAM,MAAM,CAAC;AAC1B,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EACL,WAAW,EACX,UAAU,EACV,YAAY,EACZ,UAAU,GAGX,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,EAAE,EAAE,MAAM,MAAM,CAAC;AAC1B,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EACL,WAAW,EACX,UAAU,EACV,YAAY,EACZ,UAAU,GAGX,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAChG,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAC9E,OAAO,EAAE,gBAAgB,EAAgC,MAAM,YAAY,CAAC;AAC5E,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,gBAAgB,GAGjB,MAAM,cAAc,CAAC"}
|
|
@@ -1,3 +1,12 @@
|
|
|
1
1
|
export declare function loadSetting(key: string, fallback: boolean): Promise<boolean>;
|
|
2
2
|
export declare function saveSetting(key: string, value: boolean): Promise<void>;
|
|
3
|
+
/**
|
|
4
|
+
* Same storage backend as load/saveSetting (SecureStore native,
|
|
5
|
+
* localStorage web) but for arbitrary JSON-serializable values instead
|
|
6
|
+
* of only booleans — e.g. an ordered list of ids, or a per-id map.
|
|
7
|
+
* `fallback` covers both "never saved" and "saved value doesn't parse"
|
|
8
|
+
* (a corrupt/edited-by-hand entry shouldn't crash the caller).
|
|
9
|
+
*/
|
|
10
|
+
export declare function loadJsonSetting<T>(key: string, fallback: T): Promise<T>;
|
|
11
|
+
export declare function saveJsonSetting<T>(key: string, value: T): Promise<void>;
|
|
3
12
|
//# sourceMappingURL=settings-storage.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings-storage.d.ts","sourceRoot":"","sources":["../../src/utils/settings-storage.ts"],"names":[],"mappings":"AA+BA,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAkBlF;AAED,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAgB5E"}
|
|
1
|
+
{"version":3,"file":"settings-storage.d.ts","sourceRoot":"","sources":["../../src/utils/settings-storage.ts"],"names":[],"mappings":"AA+BA,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAkBlF;AAED,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAgB5E;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAkB7E;AAED,wBAAsB,eAAe,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAiB7E"}
|
|
@@ -59,4 +59,49 @@ export async function saveSetting(key, value) {
|
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* Same storage backend as load/saveSetting (SecureStore native,
|
|
64
|
+
* localStorage web) but for arbitrary JSON-serializable values instead
|
|
65
|
+
* of only booleans — e.g. an ordered list of ids, or a per-id map.
|
|
66
|
+
* `fallback` covers both "never saved" and "saved value doesn't parse"
|
|
67
|
+
* (a corrupt/edited-by-hand entry shouldn't crash the caller).
|
|
68
|
+
*/
|
|
69
|
+
export async function loadJsonSetting(key, fallback) {
|
|
70
|
+
try {
|
|
71
|
+
const raw = Platform.OS === "web"
|
|
72
|
+
? WEB_STORAGE_AVAILABLE
|
|
73
|
+
? window.localStorage.getItem(key)
|
|
74
|
+
: null
|
|
75
|
+
: await SecureStore.getItemAsync(key);
|
|
76
|
+
if (raw === null) {
|
|
77
|
+
return fallback;
|
|
78
|
+
}
|
|
79
|
+
return JSON.parse(raw);
|
|
80
|
+
}
|
|
81
|
+
catch (e) {
|
|
82
|
+
if (__DEV__) {
|
|
83
|
+
console.warn(`[settings-storage] loadJsonSetting(${key}) threw:`, e);
|
|
84
|
+
}
|
|
85
|
+
return fallback;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
export async function saveJsonSetting(key, value) {
|
|
89
|
+
try {
|
|
90
|
+
const raw = JSON.stringify(value);
|
|
91
|
+
if (Platform.OS === "web") {
|
|
92
|
+
if (!WEB_STORAGE_AVAILABLE) {
|
|
93
|
+
warnNoStorage("save");
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
window.localStorage.setItem(key, raw);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
await SecureStore.setItemAsync(key, raw);
|
|
100
|
+
}
|
|
101
|
+
catch (e) {
|
|
102
|
+
if (__DEV__) {
|
|
103
|
+
console.warn(`[settings-storage] saveJsonSetting(${key}) threw:`, e);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
62
107
|
//# sourceMappingURL=settings-storage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings-storage.js","sourceRoot":"","sources":["../../src/utils/settings-storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,KAAK,WAAW,MAAM,mBAAmB,CAAC;AAEjD;;;;;;;;GAQG;AAEH,MAAM,qBAAqB,GACzB,QAAQ,CAAC,EAAE,KAAK,KAAK,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC;AAElF,IAAI,eAAe,GAAG,KAAK,CAAC;AAC5B,SAAS,aAAa,CAAC,MAAuB;IAC5C,IAAI,eAAe,EAAE,CAAC;QACpB,OAAO;IACT,CAAC;IACD,eAAe,GAAG,IAAI,CAAC;IACvB,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO;IACT,CAAC;IAED,OAAO,CAAC,IAAI,CACV,sBAAsB,MAAM,sEAAsE,CACnG,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,GAAW,EAAE,QAAiB;IAC9D,IAAI,CAAC;QACH,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,EAAE,CAAC;YAC1B,IAAI,CAAC,qBAAqB,EAAE,CAAC;gBAC3B,aAAa,CAAC,MAAM,CAAC,CAAC;gBACtB,OAAO,QAAQ,CAAC;YAClB,CAAC;YACD,MAAM,CAAC,GAAG,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YAC3C,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;QAC9C,CAAC;QACD,MAAM,CAAC,GAAG,MAAM,WAAW,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;QAC9C,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;IAC9C,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,CAAC,IAAI,CAAC,2BAA2B,GAAG,UAAU,EAAE,CAAC,CAAC,CAAC;QAC5D,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,GAAW,EAAE,KAAc;IAC3D,IAAI,CAAC;QACH,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,EAAE,CAAC;YAC1B,IAAI,CAAC,qBAAqB,EAAE,CAAC;gBAC3B,aAAa,CAAC,MAAM,CAAC,CAAC;gBACtB,OAAO;YACT,CAAC;YACD,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YAChD,OAAO;QACT,CAAC;QACD,MAAM,WAAW,CAAC,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACrD,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,CAAC,IAAI,CAAC,2BAA2B,GAAG,UAAU,EAAE,CAAC,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
1
|
+
{"version":3,"file":"settings-storage.js","sourceRoot":"","sources":["../../src/utils/settings-storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,KAAK,WAAW,MAAM,mBAAmB,CAAC;AAEjD;;;;;;;;GAQG;AAEH,MAAM,qBAAqB,GACzB,QAAQ,CAAC,EAAE,KAAK,KAAK,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC;AAElF,IAAI,eAAe,GAAG,KAAK,CAAC;AAC5B,SAAS,aAAa,CAAC,MAAuB;IAC5C,IAAI,eAAe,EAAE,CAAC;QACpB,OAAO;IACT,CAAC;IACD,eAAe,GAAG,IAAI,CAAC;IACvB,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO;IACT,CAAC;IAED,OAAO,CAAC,IAAI,CACV,sBAAsB,MAAM,sEAAsE,CACnG,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,GAAW,EAAE,QAAiB;IAC9D,IAAI,CAAC;QACH,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,EAAE,CAAC;YAC1B,IAAI,CAAC,qBAAqB,EAAE,CAAC;gBAC3B,aAAa,CAAC,MAAM,CAAC,CAAC;gBACtB,OAAO,QAAQ,CAAC;YAClB,CAAC;YACD,MAAM,CAAC,GAAG,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YAC3C,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;QAC9C,CAAC;QACD,MAAM,CAAC,GAAG,MAAM,WAAW,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;QAC9C,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;IAC9C,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,CAAC,IAAI,CAAC,2BAA2B,GAAG,UAAU,EAAE,CAAC,CAAC,CAAC;QAC5D,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,GAAW,EAAE,KAAc;IAC3D,IAAI,CAAC;QACH,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,EAAE,CAAC;YAC1B,IAAI,CAAC,qBAAqB,EAAE,CAAC;gBAC3B,aAAa,CAAC,MAAM,CAAC,CAAC;gBACtB,OAAO;YACT,CAAC;YACD,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YAChD,OAAO;QACT,CAAC;QACD,MAAM,WAAW,CAAC,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACrD,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,CAAC,IAAI,CAAC,2BAA2B,GAAG,UAAU,EAAE,CAAC,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAI,GAAW,EAAE,QAAW;IAC/D,IAAI,CAAC;QACH,MAAM,GAAG,GACP,QAAQ,CAAC,EAAE,KAAK,KAAK;YACnB,CAAC,CAAC,qBAAqB;gBACrB,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC;gBAClC,CAAC,CAAC,IAAI;YACR,CAAC,CAAC,MAAM,WAAW,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;QAC1C,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YACjB,OAAO,QAAQ,CAAC;QAClB,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAM,CAAC;IAC9B,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,CAAC,IAAI,CAAC,sCAAsC,GAAG,UAAU,EAAE,CAAC,CAAC,CAAC;QACvE,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAI,GAAW,EAAE,KAAQ;IAC5D,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAClC,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,EAAE,CAAC;YAC1B,IAAI,CAAC,qBAAqB,EAAE,CAAC;gBAC3B,aAAa,CAAC,MAAM,CAAC,CAAC;gBACtB,OAAO;YACT,CAAC;YACD,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACtC,OAAO;QACT,CAAC;QACD,MAAM,WAAW,CAAC,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAC3C,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,CAAC,IAAI,CAAC,sCAAsC,GAAG,UAAU,EAAE,CAAC,CAAC,CAAC;QACvE,CAAC;IACH,CAAC;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as SecureStore from "expo-secure-store";
|
|
2
|
+
import { loadJsonSetting, loadSetting, saveJsonSetting, saveSetting } from "../settings-storage";
|
|
2
3
|
|
|
3
4
|
describe("settings-storage (native path)", () => {
|
|
4
5
|
it("returns the fallback when nothing is stored", async () => {
|
|
@@ -13,3 +14,24 @@ describe("settings-storage (native path)", () => {
|
|
|
13
14
|
expect(await loadSetting("vault_setting_alpha", true)).toBe(false);
|
|
14
15
|
});
|
|
15
16
|
});
|
|
17
|
+
|
|
18
|
+
describe("loadJsonSetting / saveJsonSetting", () => {
|
|
19
|
+
it("returns the fallback when nothing is stored", async () => {
|
|
20
|
+
expect(await loadJsonSetting("vault_json_unset", ["default"])).toEqual(["default"]);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("round-trips an array via SecureStore", async () => {
|
|
24
|
+
await saveJsonSetting("vault_json_tags", ["tag-1", "tag-2", "tag-3"]);
|
|
25
|
+
expect(await loadJsonSetting("vault_json_tags", [])).toEqual(["tag-1", "tag-2", "tag-3"]);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it("round-trips an object via SecureStore", async () => {
|
|
29
|
+
await saveJsonSetting("vault_json_map", { "tag-1": true, "tag-2": false });
|
|
30
|
+
expect(await loadJsonSetting("vault_json_map", {})).toEqual({ "tag-1": true, "tag-2": false });
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("falls back on corrupt stored JSON instead of throwing", async () => {
|
|
34
|
+
await SecureStore.setItemAsync("vault_json_corrupt", "{not valid json");
|
|
35
|
+
expect(await loadJsonSetting("vault_json_corrupt", ["fallback"])).toEqual(["fallback"]);
|
|
36
|
+
});
|
|
37
|
+
});
|
package/src/utils/index.ts
CHANGED
|
@@ -10,7 +10,7 @@ export {
|
|
|
10
10
|
type Palette,
|
|
11
11
|
} from "./palette";
|
|
12
12
|
export { clearClipboardNow, copyToClipboard } from "./clipboard";
|
|
13
|
-
export { loadSetting, saveSetting } from "./settings-storage";
|
|
13
|
+
export { loadSetting, saveSetting, loadJsonSetting, saveJsonSetting } from "./settings-storage";
|
|
14
14
|
export { debounce } from "./debounce";
|
|
15
15
|
export { ApiError, extractApiError, extractErrorMessage } from "./http-error";
|
|
16
16
|
export { generatePassword, type GeneratePasswordOptions } from "./password";
|
|
@@ -66,3 +66,49 @@ export async function saveSetting(key: string, value: boolean): Promise<void> {
|
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Same storage backend as load/saveSetting (SecureStore native,
|
|
72
|
+
* localStorage web) but for arbitrary JSON-serializable values instead
|
|
73
|
+
* of only booleans — e.g. an ordered list of ids, or a per-id map.
|
|
74
|
+
* `fallback` covers both "never saved" and "saved value doesn't parse"
|
|
75
|
+
* (a corrupt/edited-by-hand entry shouldn't crash the caller).
|
|
76
|
+
*/
|
|
77
|
+
export async function loadJsonSetting<T>(key: string, fallback: T): Promise<T> {
|
|
78
|
+
try {
|
|
79
|
+
const raw =
|
|
80
|
+
Platform.OS === "web"
|
|
81
|
+
? WEB_STORAGE_AVAILABLE
|
|
82
|
+
? window.localStorage.getItem(key)
|
|
83
|
+
: null
|
|
84
|
+
: await SecureStore.getItemAsync(key);
|
|
85
|
+
if (raw === null) {
|
|
86
|
+
return fallback;
|
|
87
|
+
}
|
|
88
|
+
return JSON.parse(raw) as T;
|
|
89
|
+
} catch (e) {
|
|
90
|
+
if (__DEV__) {
|
|
91
|
+
console.warn(`[settings-storage] loadJsonSetting(${key}) threw:`, e);
|
|
92
|
+
}
|
|
93
|
+
return fallback;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export async function saveJsonSetting<T>(key: string, value: T): Promise<void> {
|
|
98
|
+
try {
|
|
99
|
+
const raw = JSON.stringify(value);
|
|
100
|
+
if (Platform.OS === "web") {
|
|
101
|
+
if (!WEB_STORAGE_AVAILABLE) {
|
|
102
|
+
warnNoStorage("save");
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
window.localStorage.setItem(key, raw);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
await SecureStore.setItemAsync(key, raw);
|
|
109
|
+
} catch (e) {
|
|
110
|
+
if (__DEV__) {
|
|
111
|
+
console.warn(`[settings-storage] saveJsonSetting(${key}) threw:`, e);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|