PageSourceSearch

https://factchecker.cloud/src/utils/storageUtils.ts

js factchecker.cloud collected 2026-10-02 01:22:03 UTC 6,643 bytes, 64 lines download raw bytes

1import { createLogger } from "/src/utils/logger.ts";
2const logger = createLogger("StorageUtils");
3export function safeGetItem(key) {
4	try {
5		return localStorage.getItem(key);
6	} catch (error) {
7		logger.error(`Failed to read ${key} from localStorage`, error);
8		return null;
9	}
10}
11export function safeSetItem(key, value) {
12	try {
13		localStorage.setItem(key, value);
14	} catch (error) {
15		logger.error(`Failed to write ${key} to localStorage`, error);
16	}
17}
18// sessionStorage 버전 — localStorage 와 동일한 Safari Private Mode 방어.
19// (예: 배너 dismiss 는 탭 단위 기억이라 sessionStorage 를 쓴다.)
20export function safeSessionGetItem(key) {
21	try {
22		return sessionStorage.getItem(key);
23	} catch (error) {
24		logger.error(`Failed to read ${key} from sessionStorage`, error);
25		return null;
26	}
27}
28export function safeSessionSetItem(key, value) {
29	try {
30		sessionStorage.setItem(key, value);
31	} catch (error) {
32		logger.error(`Failed to write ${key} to sessionStorage`, error);
33	}
34}
35export function safeRemoveItem(key) {
36	try {
37		localStorage.removeItem(key);
38	} catch (error) {
39		logger.error(`Failed to remove ${key} from localStorage`, error);
40	}
41}
42export function safeGetJson(key, fallback) {
43	try {
44		const raw = localStorage.getItem(key);
45		if (!raw) return fallback;
46		const parsed = JSON.parse(raw);
47		// 기본 타입 가드: fallback이 배열이면 parsed도 배열이어야 함.
48		// (localStorage가 수동/외부 조작되었을 때 앱 크래시 방지)
49		if (Array.isArray(fallback) && !Array.isArray(parsed)) return fallback;
50		if (!Array.isArray(fallback) && typeof fallback === "object" && fallback !== null && (typeof parsed !== "object" || parsed === null || Array.isArray(parsed))) {
51			return fallback;
52		}
53		return parsed;
54	} catch {
55		return fallback;
56	}
57}
58export function safeSetJson(key, value) {
59	try {
60		localStorage.setItem(key, JSON.stringify(value));
61	} catch {}
62}
63
64//# sourceMappingURL=data:application/json;base64,eyJtYXBwaW5ncyI6IkFBQUEsU0FBUyxvQkFBb0I7QUFFN0IsTUFBTSxTQUFTLGFBQWEsY0FBYztBQUUxQyxPQUFPLFNBQVMsWUFBWSxLQUE0QjtDQUN0RCxJQUFJO0VBQ0YsT0FBTyxhQUFhLFFBQVEsR0FBRztDQUNqQyxTQUFTLE9BQU87RUFDZCxPQUFPLE1BQU0sa0JBQWtCLElBQUkscUJBQXFCLEtBQUs7RUFDN0QsT0FBTztDQUNUO0FBQ0Y7QUFFQSxPQUFPLFNBQVMsWUFBWSxLQUFhLE9BQXFCO0NBQzVELElBQUk7RUFDRixhQUFhLFFBQVEsS0FBSyxLQUFLO0NBQ2pDLFNBQVMsT0FBTztFQUNkLE9BQU8sTUFBTSxtQkFBbUIsSUFBSSxtQkFBbUIsS0FBSztDQUM5RDtBQUNGOzs7QUFJQSxPQUFPLFNBQVMsbUJBQW1CLEtBQTRCO0NBQzdELElBQUk7RUFDRixPQUFPLGVBQWUsUUFBUSxHQUFHO0NBQ25DLFNBQVMsT0FBTztFQUNkLE9BQU8sTUFBTSxrQkFBa0IsSUFBSSx1QkFBdUIsS0FBSztFQUMvRCxPQUFPO0NBQ1Q7QUFDRjtBQUVBLE9BQU8sU0FBUyxtQkFBbUIsS0FBYSxPQUFxQjtDQUNuRSxJQUFJO0VBQ0YsZUFBZSxRQUFRLEtBQUssS0FBSztDQUNuQyxTQUFTLE9BQU87RUFDZCxPQUFPLE1BQU0sbUJBQW1CLElBQUkscUJBQXFCLEtBQUs7Q0FDaEU7QUFDRjtBQUVBLE9BQU8sU0FBUyxlQUFlLEtBQW1CO0NBQ2hELElBQUk7RUFDRixhQUFhLFdBQVcsR0FBRztDQUM3QixTQUFTLE9BQU87RUFDZCxPQUFPLE1BQU0sb0JBQW9CLElBQUkscUJBQXFCLEtBQUs7Q0FDakU7QUFDRjtBQUVBLE9BQU8sU0FBUyxZQUFlLEtBQWEsVUFBZ0I7Q0FDMUQsSUFBSTtFQUNGLE1BQU0sTUFBTSxhQUFhLFFBQVEsR0FBRztFQUNwQyxJQUFJLENBQUMsS0FBSyxPQUFPO0VBQ2pCLE1BQU0sU0FBUyxLQUFLLE1BQU0sR0FBRzs7O0VBRzdCLElBQUksTUFBTSxRQUFRLFFBQVEsS0FBSyxDQUFDLE1BQU0sUUFBUSxNQUFNLEdBQUcsT0FBTztFQUM5RCxJQUNFLENBQUMsTUFBTSxRQUFRLFFBQVEsS0FDcEIsT0FBTyxhQUFhLFlBQ3BCLGFBQWEsU0FDWixPQUFPLFdBQVcsWUFBWSxXQUFXLFFBQVEsTUFBTSxRQUFRLE1BQU0sSUFDekU7R0FDQSxPQUFPO0VBQ1Q7RUFDQSxPQUFPO0NBQ1QsUUFBUTtFQUNOLE9BQU87Q0FDVDtBQUNGO0FBRUEsT0FBTyxTQUFTLFlBQVksS0FBYSxPQUFzQjtDQUM3RCxJQUFJO0VBQ0YsYUFBYSxRQUFRLEtBQUssS0FBSyxVQUFVLEtBQUssQ0FBQztDQUNqRCxRQUFRLENBRVI7QUFDRiIsIm5hbWVzIjpbXSwic291cmNlcyI6WyJzdG9yYWdlVXRpbHMudHMiXSwidmVyc2lvbiI6Mywic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgY3JlYXRlTG9nZ2VyIH0gZnJvbSAnLi9sb2dnZXInO1xuXG5jb25zdCBsb2dnZXIgPSBjcmVhdGVMb2dnZXIoJ1N0b3JhZ2VVdGlscycpO1xuXG5leHBvcnQgZnVuY3Rpb24gc2FmZUdldEl0ZW0oa2V5OiBzdHJpbmcpOiBzdHJpbmcgfCBudWxsIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gbG9jYWxTdG9yYWdlLmdldEl0ZW0oa2V5KTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBsb2dnZXIuZXJyb3IoYEZhaWxlZCB0byByZWFkICR7a2V5fSBmcm9tIGxvY2FsU3RvcmFnZWAsIGVycm9yKTtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gc2FmZVNldEl0ZW0oa2V5OiBzdHJpbmcsIHZhbHVlOiBzdHJpbmcpOiB2b2lkIHtcbiAgdHJ5IHtcbiAgICBsb2NhbFN0b3JhZ2Uuc2V0SXRlbShrZXksIHZhbHVlKTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBsb2dnZXIuZXJyb3IoYEZhaWxlZCB0byB3cml0ZSAke2tleX0gdG8gbG9jYWxTdG9yYWdlYCwgZXJyb3IpO1xuICB9XG59XG5cbi8vIHNlc3Npb25TdG9yYWdlIOuyhOyghCDigJQgbG9jYWxTdG9yYWdlIOyZgCDrj5nsnbztlZwgU2FmYXJpIFByaXZhdGUgTW9kZSDrsKnslrQuXG4vLyAo7JiIOiDrsLDrhIggZGlzbWlzcyDripQg7YOtIOuLqOychCDquLDslrXsnbTrnbwgc2Vzc2lvblN0b3JhZ2Ug66W8IOyTtOuLpC4pXG5leHBvcnQgZnVuY3Rpb24gc2FmZVNlc3Npb25HZXRJdGVtKGtleTogc3RyaW5nKTogc3RyaW5nIHwgbnVsbCB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIHNlc3Npb25TdG9yYWdlLmdldEl0ZW0oa2V5KTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBsb2dnZXIuZXJyb3IoYEZhaWxlZCB0byByZWFkICR7a2V5fSBmcm9tIHNlc3Npb25TdG9yYWdlYCwgZXJyb3IpO1xuICAgIHJldHVybi
64BudWxsO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzYWZlU2Vzc2lvblNldEl0ZW0oa2V5OiBzdHJpbmcsIHZhbHVlOiBzdHJpbmcpOiB2b2lkIHtcbiAgdHJ5IHtcbiAgICBzZXNzaW9uU3RvcmFnZS5zZXRJdGVtKGtleSwgdmFsdWUpO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGxvZ2dlci5lcnJvcihgRmFpbGVkIHRvIHdyaXRlICR7a2V5fSB0byBzZXNzaW9uU3RvcmFnZWAsIGVycm9yKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gc2FmZVJlbW92ZUl0ZW0oa2V5OiBzdHJpbmcpOiB2b2lkIHtcbiAgdHJ5IHtcbiAgICBsb2NhbFN0b3JhZ2UucmVtb3ZlSXRlbShrZXkpO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGxvZ2dlci5lcnJvcihgRmFpbGVkIHRvIHJlbW92ZSAke2tleX0gZnJvbSBsb2NhbFN0b3JhZ2VgLCBlcnJvcik7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNhZmVHZXRKc29uPFQ+KGtleTogc3RyaW5nLCBmYWxsYmFjazogVCk6IFQge1xuICB0cnkge1xuICAgIGNvbnN0IHJhdyA9IGxvY2FsU3RvcmFnZS5nZXRJdGVtKGtleSk7XG4gICAgaWYgKCFyYXcpIHJldHVybiBmYWxsYmFjaztcbiAgICBjb25zdCBwYXJzZWQgPSBKU09OLnBhcnNlKHJhdyk7XG4gICAgLy8g6riw67O4IO2DgOyehSDqsIDrk5w6IGZhbGxiYWNr7J20IOuwsOyXtOydtOuptCBwYXJzZWTrj4Qg67Cw7Je07J207Ja07JW8IO2VqC5cbiAgICAvLyAobG9jYWxTdG9yYWdl6rCAIOyImOuPmS/smbjrtoAg7KGw7J6R65CY7JeI7J2EIOuVjCDslbEg7YGs656Y7IucIOuwqeyngClcbiAgICBpZiAoQXJyYXkuaXNBcnJheShmYWxsYmFjaykgJiYgIUFycmF5LmlzQXJyYXkocGFyc2VkKSkgcmV0dXJuIGZhbGxiYWNrO1xuICAgIGlmIChcbiAgICAgICFBcnJheS5pc0FycmF5KGZhbGxiYWNrKVxuICAgICAgJiYgdHlwZW9mIGZhbGxiYWNrID09PSAnb2JqZWN0J1xuICAgICAgJiYgZmFsbGJhY2sgIT09IG51bGxcbiAgICAgICYmICh0eXBlb2YgcGFyc2VkICE9PSAnb2JqZWN0JyB8fCBwYXJzZWQgPT09IG51bGwgfHwgQXJyYXkuaXNBcnJheShwYXJzZWQpKVxuICAgICkge1xuICAgICAgcmV0dXJuIGZhbGxiYWNrO1xuICAgIH1cbiAgICByZXR1cm4gcGFyc2VkO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gZmFsbGJhY2s7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNhZmVTZXRKc29uKGtleTogc3RyaW5nLCB2YWx1ZTogdW5rbm93bik6IHZvaWQge1xuICB0cnkge1xuICAgIGxvY2FsU3RvcmFnZS5zZXRJdGVtKGtleSwgSlNPTi5zdHJpbmdpZnkodmFsdWUpKTtcbiAgfSBjYXRjaCB7XG4gICAgLy8gaWdub3JlXG4gIH1cbn1cbiJdfQ==

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.