@autobe/ui 0.22.0 → 0.23.0

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.
Files changed (128) hide show
  1. package/lib/components/AutoBeChatMain.d.ts +6 -4
  2. package/lib/components/AutoBeChatMain.js +204 -56
  3. package/lib/components/AutoBeChatMain.js.map +1 -1
  4. package/lib/components/AutoBeChatSidebar.d.ts +36 -0
  5. package/lib/components/AutoBeChatSidebar.js +227 -0
  6. package/lib/components/AutoBeChatSidebar.js.map +1 -0
  7. package/lib/components/AutoBeConfigButton.d.ts +15 -0
  8. package/lib/components/AutoBeConfigButton.js +33 -0
  9. package/lib/components/AutoBeConfigButton.js.map +1 -0
  10. package/lib/components/AutoBeConfigModal.d.ts +59 -0
  11. package/lib/components/AutoBeConfigModal.js +294 -0
  12. package/lib/components/AutoBeConfigModal.js.map +1 -0
  13. package/lib/components/AutoBeStatusButton.d.ts +12 -0
  14. package/lib/components/AutoBeStatusButton.js +29 -0
  15. package/lib/components/AutoBeStatusButton.js.map +1 -0
  16. package/lib/components/AutoBeStatusModal.js +35 -15
  17. package/lib/components/AutoBeStatusModal.js.map +1 -1
  18. package/lib/components/common/ActionButton.d.ts +16 -0
  19. package/lib/components/common/ActionButton.js +115 -0
  20. package/lib/components/common/ActionButton.js.map +1 -0
  21. package/lib/components/common/ActionButtonGroup.d.ts +13 -0
  22. package/lib/components/common/ActionButtonGroup.js +37 -0
  23. package/lib/components/common/ActionButtonGroup.js.map +1 -0
  24. package/lib/components/common/AutoBeConfigInput.d.ts +24 -0
  25. package/lib/components/common/AutoBeConfigInput.js +90 -0
  26. package/lib/components/common/AutoBeConfigInput.js.map +1 -0
  27. package/lib/components/common/CompactSessionIndicator.d.ts +16 -0
  28. package/lib/components/common/CompactSessionIndicator.js +46 -0
  29. package/lib/components/common/CompactSessionIndicator.js.map +1 -0
  30. package/lib/components/common/CompactSessionList.d.ts +22 -0
  31. package/lib/components/common/CompactSessionList.js +40 -0
  32. package/lib/components/common/CompactSessionList.js.map +1 -0
  33. package/lib/components/common/index.d.ts +6 -0
  34. package/lib/components/common/index.js +6 -0
  35. package/lib/components/common/index.js.map +1 -1
  36. package/lib/components/events/AutoBeEventGroupMovie.d.ts +6 -0
  37. package/lib/components/events/AutoBeEventGroupMovie.js +11 -0
  38. package/lib/components/events/AutoBeEventGroupMovie.js.map +1 -0
  39. package/lib/components/events/AutoBeEventMovie.js +5 -0
  40. package/lib/components/events/AutoBeEventMovie.js.map +1 -1
  41. package/lib/components/events/AutoBeValidateEventMovie.js +1 -3
  42. package/lib/components/events/AutoBeValidateEventMovie.js.map +1 -1
  43. package/lib/components/events/common/CollapsibleEventGroup.d.ts +1 -1
  44. package/lib/components/events/groups/ValidateEventGroup.d.ts +1 -1
  45. package/lib/components/events/utils/eventGrouper.js.map +1 -1
  46. package/lib/components/index.d.ts +6 -0
  47. package/lib/components/index.js +7 -0
  48. package/lib/components/index.js.map +1 -1
  49. package/lib/components/upload/AutoBeChatUploadBox.js +75 -33
  50. package/lib/components/upload/AutoBeChatUploadBox.js.map +1 -1
  51. package/lib/context/AutoBeAgentContext.d.ts +22 -11
  52. package/lib/context/AutoBeAgentContext.js +127 -11
  53. package/lib/context/AutoBeAgentContext.js.map +1 -1
  54. package/lib/context/AutoBeAgentSessionList.d.ts +12 -0
  55. package/lib/context/AutoBeAgentSessionList.js +37 -0
  56. package/lib/context/AutoBeAgentSessionList.js.map +1 -0
  57. package/lib/context/SearchParamsContext.d.ts +10 -0
  58. package/lib/context/SearchParamsContext.js +29 -0
  59. package/lib/context/SearchParamsContext.js.map +1 -0
  60. package/lib/index.d.ts +4 -0
  61. package/lib/index.js +4 -0
  62. package/lib/index.js.map +1 -1
  63. package/lib/structure/AutoBeListener.d.ts +6 -0
  64. package/lib/structure/AutoBeListener.js +21 -4
  65. package/lib/structure/AutoBeListener.js.map +1 -1
  66. package/lib/structure/IAutoBeAgentSessionStorageStrategy.d.ts +35 -0
  67. package/lib/structure/IAutoBeAgentSessionStorageStrategy.js +30 -0
  68. package/lib/structure/IAutoBeAgentSessionStorageStrategy.js.map +1 -0
  69. package/lib/structure/index.d.ts +1 -0
  70. package/lib/structure/index.js +1 -0
  71. package/lib/structure/index.js.map +1 -1
  72. package/lib/types/config.d.ts +26 -0
  73. package/lib/types/config.js +14 -0
  74. package/lib/types/config.js.map +1 -0
  75. package/lib/types/index.d.ts +1 -0
  76. package/lib/types/index.js +18 -0
  77. package/lib/types/index.js.map +1 -0
  78. package/lib/utils/__tests__/crypto.test.d.ts +1 -0
  79. package/lib/utils/__tests__/crypto.test.js +222 -0
  80. package/lib/utils/__tests__/crypto.test.js.map +1 -0
  81. package/lib/utils/__tests__/storage.test.d.ts +1 -0
  82. package/lib/utils/__tests__/storage.test.js +174 -0
  83. package/lib/utils/__tests__/storage.test.js.map +1 -0
  84. package/lib/utils/crypto.d.ts +18 -0
  85. package/lib/utils/crypto.js +84 -0
  86. package/lib/utils/crypto.js.map +1 -0
  87. package/lib/utils/index.d.ts +2 -0
  88. package/lib/utils/index.js +2 -0
  89. package/lib/utils/index.js.map +1 -1
  90. package/lib/utils/storage.d.ts +29 -0
  91. package/lib/utils/storage.js +93 -0
  92. package/lib/utils/storage.js.map +1 -0
  93. package/package.json +11 -3
  94. package/src/components/AutoBeChatMain.tsx +329 -131
  95. package/src/components/AutoBeChatSidebar.tsx +414 -0
  96. package/src/components/AutoBeConfigButton.tsx +83 -0
  97. package/src/components/AutoBeConfigModal.tsx +444 -0
  98. package/src/components/AutoBeStatusButton.tsx +75 -0
  99. package/src/components/AutoBeStatusModal.tsx +55 -54
  100. package/src/components/common/ActionButton.tsx +205 -0
  101. package/src/components/common/ActionButtonGroup.tsx +80 -0
  102. package/src/components/common/AutoBeConfigInput.tsx +185 -0
  103. package/src/components/common/CompactSessionIndicator.tsx +73 -0
  104. package/src/components/common/CompactSessionList.tsx +82 -0
  105. package/src/components/common/index.ts +6 -0
  106. package/src/components/events/AutoBeEventGroupMovie.tsx +18 -0
  107. package/src/components/events/AutoBeEventMovie.tsx +5 -0
  108. package/src/components/events/AutoBeValidateEventMovie.tsx +7 -9
  109. package/src/components/events/common/CollapsibleEventGroup.tsx +1 -1
  110. package/src/components/events/groups/ValidateEventGroup.tsx +1 -1
  111. package/src/components/events/utils/eventGrouper.tsx +2 -1
  112. package/src/components/index.ts +6 -0
  113. package/src/components/upload/AutoBeChatUploadBox.tsx +94 -44
  114. package/src/context/AutoBeAgentContext.tsx +201 -22
  115. package/src/context/AutoBeAgentSessionList.tsx +58 -0
  116. package/src/context/SearchParamsContext.tsx +49 -0
  117. package/src/index.ts +4 -0
  118. package/src/structure/AutoBeListener.ts +32 -6
  119. package/src/structure/IAutoBeAgentSessionStorageStrategy.ts +87 -0
  120. package/src/structure/index.ts +1 -0
  121. package/src/types/config.ts +44 -0
  122. package/src/types/index.ts +1 -0
  123. package/src/utils/__tests__/crypto.test.ts +286 -0
  124. package/src/utils/__tests__/storage.test.ts +229 -0
  125. package/src/utils/crypto.ts +95 -0
  126. package/src/utils/index.ts +2 -0
  127. package/src/utils/storage.ts +96 -0
  128. package/vitest.config.ts +15 -0
@@ -0,0 +1,229 @@
1
+ import { beforeEach, describe, expect, test, vi } from "vitest";
2
+
3
+ import {
4
+ clearEncryptedSessionStorage,
5
+ getEncryptedSessionStorage,
6
+ hasEncryptedSessionStorage,
7
+ removeEncryptedSessionStorage,
8
+ setEncryptedSessionStorage,
9
+ } from "../storage";
10
+
11
+ // Mock sessionStorage for testing
12
+ const mockSessionStorage = {
13
+ store: new Map<string, string>(),
14
+ getItem: vi.fn((key: string) => mockSessionStorage.store.get(key) || null),
15
+ setItem: vi.fn((key: string, value: string) => {
16
+ mockSessionStorage.store.set(key, value);
17
+ }),
18
+ removeItem: vi.fn((key: string) => {
19
+ mockSessionStorage.store.delete(key);
20
+ }),
21
+ clear: vi.fn(() => {
22
+ mockSessionStorage.store.clear();
23
+ }),
24
+ };
25
+
26
+ // Mock global sessionStorage
27
+ Object.defineProperty(global, "sessionStorage", {
28
+ value: mockSessionStorage,
29
+ writable: true,
30
+ });
31
+
32
+ Object.defineProperty(global, "window", {
33
+ value: { sessionStorage: mockSessionStorage },
34
+ writable: true,
35
+ });
36
+
37
+ describe("Storage Utils", () => {
38
+ beforeEach(() => {
39
+ mockSessionStorage.store.clear();
40
+ vi.clearAllMocks();
41
+ });
42
+
43
+ describe("encrypted sessionStorage operations", () => {
44
+ test("should store and retrieve encrypted data", () => {
45
+ const key = "test_key";
46
+ const value = "sk-test123456789";
47
+
48
+ setEncryptedSessionStorage(key, value);
49
+ const retrieved = getEncryptedSessionStorage(key);
50
+
51
+ expect(retrieved).toBe(value);
52
+ expect(mockSessionStorage.setItem).toHaveBeenCalledWith(
53
+ key,
54
+ expect.any(String),
55
+ );
56
+ expect(mockSessionStorage.getItem).toHaveBeenCalledWith(key);
57
+ });
58
+
59
+ test("should store encrypted value, not plain text", () => {
60
+ const key = "test_encrypted";
61
+ const value = "secret-api-key";
62
+
63
+ setEncryptedSessionStorage(key, value);
64
+ const storedValue = mockSessionStorage.store.get(key);
65
+
66
+ expect(storedValue).not.toBe(value); // Should not store plain text
67
+ expect(storedValue).toBeTruthy(); // Should store something
68
+ expect(storedValue!.length).toBeGreaterThan(0); // Should have content
69
+ });
70
+
71
+ test("should handle empty values correctly", () => {
72
+ const key = "empty_test";
73
+ const value = "";
74
+
75
+ setEncryptedSessionStorage(key, value);
76
+ const retrieved = getEncryptedSessionStorage(key);
77
+
78
+ expect(retrieved).toBe("");
79
+ });
80
+
81
+ test("should return empty string for non-existent keys", () => {
82
+ const result = getEncryptedSessionStorage("non_existent_key");
83
+ expect(result).toBe("");
84
+ });
85
+
86
+ test("should remove encrypted data", () => {
87
+ const key = "test_remove";
88
+ const value = "test-value";
89
+
90
+ setEncryptedSessionStorage(key, value);
91
+ expect(getEncryptedSessionStorage(key)).toBe(value);
92
+
93
+ removeEncryptedSessionStorage(key);
94
+ expect(getEncryptedSessionStorage(key)).toBe("");
95
+ expect(mockSessionStorage.removeItem).toHaveBeenCalledWith(key);
96
+ });
97
+
98
+ test("should check if encrypted data exists", () => {
99
+ const key = "existence_test";
100
+ const value = "test-value";
101
+
102
+ // Initially should not exist
103
+ expect(hasEncryptedSessionStorage(key)).toBe(false);
104
+
105
+ // After storing should exist
106
+ setEncryptedSessionStorage(key, value);
107
+ expect(hasEncryptedSessionStorage(key)).toBe(true);
108
+
109
+ // After removing should not exist
110
+ removeEncryptedSessionStorage(key);
111
+ expect(hasEncryptedSessionStorage(key)).toBe(false);
112
+ });
113
+
114
+ test("should handle storage errors gracefully", () => {
115
+ const originalSetItem = mockSessionStorage.setItem;
116
+ mockSessionStorage.setItem = vi.fn(() => {
117
+ throw new Error("Storage quota exceeded");
118
+ });
119
+
120
+ // Should throw error with meaningful message
121
+ expect(() => {
122
+ setEncryptedSessionStorage("test", "value");
123
+ }).toThrow(
124
+ 'Failed to store encrypted data for key "test": Storage quota exceeded',
125
+ );
126
+
127
+ mockSessionStorage.setItem = originalSetItem; // Restore
128
+ });
129
+
130
+ test("should clear all sessionStorage data", () => {
131
+ // Mock setItem to not throw for this test
132
+ const originalSetItem = mockSessionStorage.setItem;
133
+ mockSessionStorage.setItem = vi.fn((key: string, value: string) => {
134
+ mockSessionStorage.store.set(key, value);
135
+ });
136
+
137
+ // Store some test data
138
+ setEncryptedSessionStorage("key1", "value1");
139
+ setEncryptedSessionStorage("key2", "value2");
140
+
141
+ expect(hasEncryptedSessionStorage("key1")).toBe(true);
142
+ expect(hasEncryptedSessionStorage("key2")).toBe(true);
143
+
144
+ // Clear all
145
+ clearEncryptedSessionStorage();
146
+
147
+ expect(hasEncryptedSessionStorage("key1")).toBe(false);
148
+ expect(hasEncryptedSessionStorage("key2")).toBe(false);
149
+ expect(mockSessionStorage.clear).toHaveBeenCalled();
150
+
151
+ mockSessionStorage.setItem = originalSetItem; // Restore
152
+ });
153
+ });
154
+
155
+ describe("Unicode and special data", () => {
156
+ const testCases = [
157
+ { key: "korean", value: "안녕하세요" },
158
+ { key: "emoji", value: "🚀🔐💎✨" },
159
+ { key: "mixed", value: "Hello 안녕 🚀 World!" },
160
+ { key: "api_key", value: "sk-proj-1234567890abcdefghijklmnop" },
161
+ { key: "json", value: '{"name":"test","value":123}' },
162
+ { key: "multiline", value: "line1\nline2\nline3" },
163
+ ];
164
+
165
+ test.each(testCases)(
166
+ "should handle $key: $value correctly",
167
+ ({ key, value }) => {
168
+ // Mock setItem to not throw for unicode tests
169
+ const originalSetItem = mockSessionStorage.setItem;
170
+ mockSessionStorage.setItem = vi.fn((key: string, value: string) => {
171
+ mockSessionStorage.store.set(key, value);
172
+ });
173
+
174
+ setEncryptedSessionStorage(key, value);
175
+ const retrieved = getEncryptedSessionStorage(key);
176
+
177
+ expect(retrieved).toBe(value);
178
+ expect(hasEncryptedSessionStorage(key)).toBe(true);
179
+
180
+ // Verify it's actually encrypted in storage
181
+ const rawStored = mockSessionStorage.store.get(key);
182
+ expect(rawStored).not.toBe(value);
183
+ expect(rawStored).toBeTruthy();
184
+
185
+ mockSessionStorage.setItem = originalSetItem; // Restore
186
+ },
187
+ );
188
+ });
189
+
190
+ describe("Edge cases", () => {
191
+ test("should handle null/undefined gracefully", () => {
192
+ // These should not throw
193
+ expect(() => getEncryptedSessionStorage("")).not.toThrow();
194
+ expect(() => hasEncryptedSessionStorage("")).not.toThrow();
195
+ expect(() => removeEncryptedSessionStorage("")).not.toThrow();
196
+ });
197
+
198
+ test("should handle SSR environment (no window)", () => {
199
+ const originalWindow = global.window;
200
+ // @ts-ignore
201
+ delete global.window;
202
+
203
+ // Should not throw and return safe defaults
204
+ expect(() => {
205
+ setEncryptedSessionStorage("test", "value");
206
+ const result = getEncryptedSessionStorage("test");
207
+ expect(result).toBe("");
208
+ const exists = hasEncryptedSessionStorage("test");
209
+ expect(exists).toBe(false);
210
+ removeEncryptedSessionStorage("test");
211
+ clearEncryptedSessionStorage();
212
+ }).not.toThrow();
213
+
214
+ global.window = originalWindow; // Restore
215
+ });
216
+
217
+ test("should handle corrupted storage data", () => {
218
+ const key = "corrupted_test";
219
+
220
+ // Manually put invalid encrypted data
221
+ mockSessionStorage.store.set(key, "invalid-base64-data!");
222
+
223
+ // Should throw error on corrupted data
224
+ expect(() => {
225
+ getEncryptedSessionStorage(key);
226
+ }).toThrow('Failed to retrieve encrypted data for key "corrupted_test"');
227
+ });
228
+ });
229
+ });
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Simple and reliable encryption utilities using browser built-in functions
3
+ * Uses TextEncoder/TextDecoder for proper Unicode support + XOR + Base64
4
+ */
5
+
6
+ const ENCRYPTION_KEY = "AutoBE_Secret_2024_v3.0_Unicode"; // Unicode-safe key
7
+
8
+ /**
9
+ * Simple encrypt using TextEncoder for Unicode safety
10
+ *
11
+ * @param text - Text to encrypt
12
+ * @returns Encrypted base64 string
13
+ */
14
+ export const encrypt = (text: string): string => {
15
+ if (!text) return "";
16
+
17
+ try {
18
+ // Use TextEncoder for proper Unicode → UTF-8 bytes conversion
19
+ const encoder = new TextEncoder();
20
+ const textBytes = encoder.encode(text);
21
+
22
+ // Generate simple salt
23
+ const salt = Math.random().toString(36).substring(2, 10);
24
+ const keyBytes = encoder.encode(ENCRYPTION_KEY + salt);
25
+
26
+ // XOR encryption on bytes level
27
+ const encryptedBytes = new Uint8Array(textBytes.length);
28
+ for (let i = 0; i < textBytes.length; i++) {
29
+ encryptedBytes[i] = textBytes[i] ^ keyBytes[i % keyBytes.length];
30
+ }
31
+
32
+ // Convert to hex string for safe concatenation
33
+ const encryptedHex = Array.from(encryptedBytes)
34
+ .map((b) => b.toString(16).padStart(2, "0"))
35
+ .join("");
36
+
37
+ // Combine salt + encrypted hex
38
+ const combined = salt + ":" + encryptedHex;
39
+
40
+ // Base64 encode the final result (handle Unicode properly)
41
+ const result = btoa(unescape(encodeURIComponent(combined)));
42
+ return result;
43
+ } catch (error) {
44
+ throw new Error(
45
+ `Encryption failed: ${error instanceof Error ? error.message : String(error)}`,
46
+ );
47
+ }
48
+ };
49
+
50
+ /**
51
+ * Simple decrypt using TextDecoder for Unicode safety
52
+ *
53
+ * @param encryptedText - Base64 encrypted string
54
+ * @returns Decrypted plain text
55
+ */
56
+ export const decrypt = (encryptedText: string): string => {
57
+ if (!encryptedText) return "";
58
+
59
+ try {
60
+ // Base64 decode (handle Unicode properly)
61
+ const combined = decodeURIComponent(escape(atob(encryptedText)));
62
+ const parts = combined.split(":");
63
+
64
+ if (parts.length !== 2) {
65
+ throw new Error("Invalid encrypted format: expected salt:data format");
66
+ }
67
+
68
+ const salt = parts[0];
69
+ const encryptedHex = parts[1];
70
+
71
+ // Convert hex back to bytes
72
+ const encryptedBytes = new Uint8Array(
73
+ encryptedHex.match(/.{2}/g)?.map((hex) => parseInt(hex, 16)) || [],
74
+ );
75
+
76
+ // Recreate key
77
+ const encoder = new TextEncoder();
78
+ const keyBytes = encoder.encode(ENCRYPTION_KEY + salt);
79
+
80
+ // XOR decryption
81
+ const decryptedBytes = new Uint8Array(encryptedBytes.length);
82
+ for (let i = 0; i < encryptedBytes.length; i++) {
83
+ decryptedBytes[i] = encryptedBytes[i] ^ keyBytes[i % keyBytes.length];
84
+ }
85
+
86
+ // Use TextDecoder for proper UTF-8 → Unicode conversion
87
+ const decoder = new TextDecoder();
88
+ const result = decoder.decode(decryptedBytes);
89
+ return result;
90
+ } catch (error) {
91
+ throw new Error(
92
+ `Decryption failed: ${error instanceof Error ? error.message : String(error)}`,
93
+ );
94
+ }
95
+ };
@@ -1,4 +1,6 @@
1
1
  export * from "./AutoBeFileUploader";
2
2
  export * from "./AutoBeVoiceRecorder";
3
3
  export * from "./time";
4
+ export * from "./crypto";
5
+ export * from "./storage";
4
6
  export * from "./number";
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Encrypted sessionStorage utilities Provides secure storage functions using
3
+ * encryption
4
+ */
5
+ import { decrypt, encrypt } from "./crypto";
6
+
7
+ /**
8
+ * Safely store encrypted data in sessionStorage
9
+ *
10
+ * @param key - Storage key
11
+ * @param value - Plain text value to encrypt and store
12
+ */
13
+ export const setEncryptedSessionStorage = (
14
+ key: string,
15
+ value: string,
16
+ ): void => {
17
+ if (typeof window === "undefined") return;
18
+
19
+ try {
20
+ const encrypted = encrypt(value);
21
+ sessionStorage.setItem(key, encrypted);
22
+ } catch (error) {
23
+ throw new Error(
24
+ `Failed to store encrypted data for key "${key}": ${error instanceof Error ? error.message : String(error)}`,
25
+ );
26
+ }
27
+ };
28
+
29
+ /**
30
+ * Safely retrieve and decrypt data from sessionStorage
31
+ *
32
+ * @param key - Storage key
33
+ * @returns Decrypted plain text value
34
+ */
35
+ export const getEncryptedSessionStorage = (key: string): string => {
36
+ if (typeof window === "undefined") return "";
37
+
38
+ try {
39
+ const encrypted = sessionStorage.getItem(key);
40
+ if (!encrypted) return "";
41
+ return decrypt(encrypted);
42
+ } catch (error) {
43
+ throw new Error(
44
+ `Failed to retrieve encrypted data for key "${key}": ${error instanceof Error ? error.message : String(error)}`,
45
+ );
46
+ }
47
+ };
48
+
49
+ /**
50
+ * Remove encrypted data from sessionStorage
51
+ *
52
+ * @param key - Storage key
53
+ */
54
+ export const removeEncryptedSessionStorage = (key: string): void => {
55
+ if (typeof window === "undefined") return;
56
+
57
+ try {
58
+ sessionStorage.removeItem(key);
59
+ } catch (error) {
60
+ throw new Error(
61
+ `Failed to remove encrypted data for key "${key}": ${error instanceof Error ? error.message : String(error)}`,
62
+ );
63
+ }
64
+ };
65
+
66
+ /**
67
+ * Check if encrypted data exists in sessionStorage
68
+ *
69
+ * @param key - Storage key
70
+ * @returns Whether the key exists and has a value
71
+ */
72
+ export const hasEncryptedSessionStorage = (key: string): boolean => {
73
+ if (typeof window === "undefined") return false;
74
+
75
+ try {
76
+ const value = sessionStorage.getItem(key);
77
+ return value !== null && value !== "";
78
+ } catch (error) {
79
+ throw new Error(
80
+ `Failed to check encrypted data for key "${key}": ${error instanceof Error ? error.message : String(error)}`,
81
+ );
82
+ }
83
+ };
84
+
85
+ /** Clear all sessionStorage data (use with caution) */
86
+ export const clearEncryptedSessionStorage = (): void => {
87
+ if (typeof window === "undefined") return;
88
+
89
+ try {
90
+ sessionStorage.clear();
91
+ } catch (error) {
92
+ throw new Error(
93
+ `Failed to clear sessionStorage: ${error instanceof Error ? error.message : String(error)}`,
94
+ );
95
+ }
96
+ };
@@ -0,0 +1,15 @@
1
+ import { defineConfig } from "vitest/config";
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ environment: "happy-dom",
6
+ globals: true,
7
+ setupFiles: [],
8
+ include: ["src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"],
9
+ exclude: ["node_modules", "lib", "dist"],
10
+ coverage: {
11
+ reporter: ["text", "json", "html"],
12
+ exclude: ["node_modules/", "src/**/*.test.ts", "src/**/*.spec.ts"],
13
+ },
14
+ },
15
+ });