@uploadista/client-browser 0.0.3

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 (83) hide show
  1. package/.turbo/turbo-build.log +5 -0
  2. package/.turbo/turbo-check.log +130 -0
  3. package/AUTO_CAPABILITIES.md +98 -0
  4. package/FRAMEWORK_INTEGRATION.md +407 -0
  5. package/LICENSE +21 -0
  6. package/README.md +795 -0
  7. package/SMART_CHUNKING.md +140 -0
  8. package/dist/client/create-uploadista-client.d.ts +182 -0
  9. package/dist/client/create-uploadista-client.d.ts.map +1 -0
  10. package/dist/client/create-uploadista-client.js +76 -0
  11. package/dist/client/index.d.ts +2 -0
  12. package/dist/client/index.d.ts.map +1 -0
  13. package/dist/client/index.js +1 -0
  14. package/dist/framework-utils.d.ts +201 -0
  15. package/dist/framework-utils.d.ts.map +1 -0
  16. package/dist/framework-utils.js +282 -0
  17. package/dist/http-client.d.ts +44 -0
  18. package/dist/http-client.d.ts.map +1 -0
  19. package/dist/http-client.js +489 -0
  20. package/dist/index.d.ts +8 -0
  21. package/dist/index.d.ts.map +1 -0
  22. package/dist/index.js +7 -0
  23. package/dist/services/abort-controller-factory.d.ts +30 -0
  24. package/dist/services/abort-controller-factory.d.ts.map +1 -0
  25. package/dist/services/abort-controller-factory.js +98 -0
  26. package/dist/services/checksum-service.d.ts +30 -0
  27. package/dist/services/checksum-service.d.ts.map +1 -0
  28. package/dist/services/checksum-service.js +44 -0
  29. package/dist/services/create-browser-services.d.ts +36 -0
  30. package/dist/services/create-browser-services.d.ts.map +1 -0
  31. package/dist/services/create-browser-services.js +56 -0
  32. package/dist/services/file-reader.d.ts +91 -0
  33. package/dist/services/file-reader.d.ts.map +1 -0
  34. package/dist/services/file-reader.js +251 -0
  35. package/dist/services/fingerprint-service.d.ts +41 -0
  36. package/dist/services/fingerprint-service.d.ts.map +1 -0
  37. package/dist/services/fingerprint-service.js +64 -0
  38. package/dist/services/id-generation/id-generation.d.ts +40 -0
  39. package/dist/services/id-generation/id-generation.d.ts.map +1 -0
  40. package/dist/services/id-generation/id-generation.js +58 -0
  41. package/dist/services/platform-service.d.ts +38 -0
  42. package/dist/services/platform-service.d.ts.map +1 -0
  43. package/dist/services/platform-service.js +221 -0
  44. package/dist/services/storage/local-storage-service.d.ts +55 -0
  45. package/dist/services/storage/local-storage-service.d.ts.map +1 -0
  46. package/dist/services/storage/local-storage-service.js +178 -0
  47. package/dist/services/storage/session-storage-service.d.ts +55 -0
  48. package/dist/services/storage/session-storage-service.d.ts.map +1 -0
  49. package/dist/services/storage/session-storage-service.js +179 -0
  50. package/dist/services/websocket-factory.d.ts +46 -0
  51. package/dist/services/websocket-factory.d.ts.map +1 -0
  52. package/dist/services/websocket-factory.js +196 -0
  53. package/dist/types/index.d.ts +2 -0
  54. package/dist/types/index.d.ts.map +1 -0
  55. package/dist/types/index.js +1 -0
  56. package/dist/types/upload-input.d.ts +26 -0
  57. package/dist/types/upload-input.d.ts.map +1 -0
  58. package/dist/types/upload-input.js +1 -0
  59. package/dist/utils/hash-util.d.ts +60 -0
  60. package/dist/utils/hash-util.d.ts.map +1 -0
  61. package/dist/utils/hash-util.js +75 -0
  62. package/package.json +32 -0
  63. package/src/client/create-uploadista-client.ts +150 -0
  64. package/src/client/index.ts +1 -0
  65. package/src/framework-utils.ts +446 -0
  66. package/src/http-client.ts +546 -0
  67. package/src/index.ts +8 -0
  68. package/src/services/abort-controller-factory.ts +108 -0
  69. package/src/services/checksum-service.ts +46 -0
  70. package/src/services/create-browser-services.ts +81 -0
  71. package/src/services/file-reader.ts +344 -0
  72. package/src/services/fingerprint-service.ts +67 -0
  73. package/src/services/id-generation/id-generation.ts +60 -0
  74. package/src/services/platform-service.ts +231 -0
  75. package/src/services/storage/local-storage-service.ts +187 -0
  76. package/src/services/storage/session-storage-service.ts +188 -0
  77. package/src/services/websocket-factory.ts +212 -0
  78. package/src/types/index.ts +1 -0
  79. package/src/types/upload-input.ts +25 -0
  80. package/src/utils/hash-util.ts +79 -0
  81. package/tsconfig.json +22 -0
  82. package/tsconfig.tsbuildinfo +1 -0
  83. package/vitest.config.ts +15 -0
@@ -0,0 +1,231 @@
1
+ import type { PlatformService, Timeout } from "@uploadista/client-core";
2
+
3
+ /**
4
+ * Creates a browser-specific platform service that provides environment capabilities.
5
+ *
6
+ * This service abstracts platform-specific functionality and provides a consistent
7
+ * interface for the Uploadista client to interact with browser APIs. It handles:
8
+ * - Timer management (setTimeout/clearTimeout)
9
+ * - Environment detection (browser vs. Node.js)
10
+ * - Network connectivity status
11
+ * - File object detection and metadata extraction
12
+ *
13
+ * This abstraction allows the core upload logic to remain platform-agnostic while
14
+ * still accessing browser-specific features when needed.
15
+ *
16
+ * @returns A PlatformService configured for browser environments
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * import { createBrowserPlatformService } from '@uploadista/client-browser';
21
+ *
22
+ * const platform = createBrowserPlatformService();
23
+ *
24
+ * // Check if running in browser
25
+ * console.log('Is browser:', platform.isBrowser()); // true
26
+ *
27
+ * // Check network status
28
+ * console.log('Is online:', platform.isOnline()); // true or false
29
+ *
30
+ * // Extract file metadata
31
+ * const fileInput = document.querySelector('input[type="file"]');
32
+ * const file = fileInput.files[0];
33
+ * console.log('File name:', platform.getFileName(file));
34
+ * console.log('File type:', platform.getFileType(file));
35
+ * console.log('File size:', platform.getFileSize(file));
36
+ * ```
37
+ */
38
+ export function createBrowserPlatformService(): PlatformService {
39
+ return {
40
+ /**
41
+ * Schedules a function to be executed after a specified delay.
42
+ *
43
+ * Wraps the browser's native `setTimeout` function.
44
+ *
45
+ * @param callback - Function to execute after the delay
46
+ * @param ms - Delay in milliseconds before executing the callback
47
+ * @returns A timeout ID that can be passed to clearTimeout
48
+ *
49
+ * @example
50
+ * ```typescript
51
+ * const timeoutId = platform.setTimeout(() => {
52
+ * console.log('Executed after 1 second');
53
+ * }, 1000);
54
+ * ```
55
+ */
56
+ setTimeout: (callback: () => void, ms: number | undefined) => {
57
+ return globalThis.setTimeout(callback, ms);
58
+ },
59
+
60
+ /**
61
+ * Cancels a timeout previously scheduled with setTimeout.
62
+ *
63
+ * Wraps the browser's native `clearTimeout` function.
64
+ *
65
+ * @param id - The timeout ID returned by setTimeout
66
+ *
67
+ * @example
68
+ * ```typescript
69
+ * const timeoutId = platform.setTimeout(() => { }, 1000);
70
+ * platform.clearTimeout(timeoutId); // Cancel the timeout
71
+ * ```
72
+ */
73
+ clearTimeout: (id: Timeout) => {
74
+ globalThis.clearTimeout(id as number);
75
+ },
76
+
77
+ /**
78
+ * Checks if the code is running in a browser environment.
79
+ *
80
+ * Detects browser by checking for the existence of the `window` object.
81
+ * This is useful for conditional logic that should only run in browsers.
82
+ *
83
+ * @returns `true` if running in a browser, `false` otherwise
84
+ *
85
+ * @example
86
+ * ```typescript
87
+ * if (platform.isBrowser()) {
88
+ * // Browser-specific code
89
+ * console.log('Running in browser');
90
+ * }
91
+ * ```
92
+ */
93
+ isBrowser: () => {
94
+ return typeof window !== "undefined";
95
+ },
96
+
97
+ /**
98
+ * Checks if the browser is currently online.
99
+ *
100
+ * Uses the Navigator Online Status API (`navigator.onLine`) to determine
101
+ * network connectivity. Note that this only indicates if the device has
102
+ * a network connection, not if it can reach the internet.
103
+ *
104
+ * @returns `true` if online, `false` if offline, defaults to `true` if not in browser
105
+ *
106
+ * @example
107
+ * ```typescript
108
+ * if (platform.isOnline()) {
109
+ * // Proceed with upload
110
+ * await client.upload(file);
111
+ * } else {
112
+ * console.log('Waiting for network connection...');
113
+ * }
114
+ *
115
+ * // Listen for online/offline events
116
+ * window.addEventListener('online', () => {
117
+ * console.log('Back online, resuming upload');
118
+ * });
119
+ * ```
120
+ */
121
+ isOnline: () => {
122
+ if (typeof navigator !== "undefined") {
123
+ return navigator.onLine;
124
+ }
125
+ return true;
126
+ },
127
+
128
+ /**
129
+ * Checks if a value is a File object.
130
+ *
131
+ * Type guard to determine if an unknown value is a browser File object.
132
+ * Useful for validating upload inputs and conditional file handling.
133
+ *
134
+ * @param value - The value to check
135
+ * @returns `true` if the value is a File instance, `false` otherwise
136
+ *
137
+ * @example
138
+ * ```typescript
139
+ * const input = getUploadInput(); // unknown type
140
+ *
141
+ * if (platform.isFileLike(input)) {
142
+ * // TypeScript knows input is a File here
143
+ * console.log('Uploading file:', input.name);
144
+ * }
145
+ * ```
146
+ */
147
+ isFileLike: (value: unknown) => {
148
+ return value instanceof File;
149
+ },
150
+
151
+ /**
152
+ * Extracts the file name from a File object.
153
+ *
154
+ * @param file - The file to extract the name from
155
+ * @returns The file name string, or `undefined` if not a File
156
+ *
157
+ * @example
158
+ * ```typescript
159
+ * const file = new File(['content'], 'document.pdf');
160
+ * const name = platform.getFileName(file);
161
+ * console.log(name); // "document.pdf"
162
+ * ```
163
+ */
164
+ getFileName: (file: unknown) => {
165
+ if (file instanceof File) {
166
+ return file.name;
167
+ }
168
+ return undefined;
169
+ },
170
+
171
+ /**
172
+ * Extracts the MIME type from a File object.
173
+ *
174
+ * @param file - The file to extract the type from
175
+ * @returns The MIME type string, or `undefined` if not a File
176
+ *
177
+ * @example
178
+ * ```typescript
179
+ * const file = new File(['content'], 'image.png', { type: 'image/png' });
180
+ * const type = platform.getFileType(file);
181
+ * console.log(type); // "image/png"
182
+ * ```
183
+ */
184
+ getFileType: (file: unknown) => {
185
+ if (file instanceof File) {
186
+ return file.type;
187
+ }
188
+ return undefined;
189
+ },
190
+
191
+ /**
192
+ * Extracts the file size in bytes from a File object.
193
+ *
194
+ * @param file - The file to extract the size from
195
+ * @returns The file size in bytes, or `undefined` if not a File
196
+ *
197
+ * @example
198
+ * ```typescript
199
+ * const file = new File(['Hello'], 'greeting.txt');
200
+ * const size = platform.getFileSize(file);
201
+ * console.log(size); // 5 (bytes)
202
+ * ```
203
+ */
204
+ getFileSize: (file: unknown) => {
205
+ if (file instanceof File) {
206
+ return file.size;
207
+ }
208
+ return undefined;
209
+ },
210
+
211
+ /**
212
+ * Extracts the last modified timestamp from a File object.
213
+ *
214
+ * @param file - The file to extract the timestamp from
215
+ * @returns The last modified timestamp in milliseconds since epoch, or `undefined` if not a File
216
+ *
217
+ * @example
218
+ * ```typescript
219
+ * const file = new File(['content'], 'data.txt');
220
+ * const lastModified = platform.getFileLastModified(file);
221
+ * console.log(new Date(lastModified)); // Date object of when file was last modified
222
+ * ```
223
+ */
224
+ getFileLastModified: (file: unknown) => {
225
+ if (file instanceof File) {
226
+ return file.lastModified;
227
+ }
228
+ return undefined;
229
+ },
230
+ };
231
+ }
@@ -0,0 +1,187 @@
1
+ import type { StorageService } from "@uploadista/client-core";
2
+
3
+ /**
4
+ * Creates a browser storage service using localStorage for persistent data storage.
5
+ *
6
+ * This service provides a key-value storage interface backed by the browser's
7
+ * localStorage API. Data stored with this service persists across browser sessions
8
+ * and page reloads until explicitly deleted or cleared by the user.
9
+ *
10
+ * Use cases include:
11
+ * - Persisting upload state for resumable uploads
12
+ * - Caching file metadata and fingerprints
13
+ * - Storing user preferences and settings
14
+ * - Maintaining upload history
15
+ *
16
+ * **Important notes:**
17
+ * - localStorage has a typical limit of 5-10MB per origin
18
+ * - Data is stored as strings (objects are JSON-serialized)
19
+ * - localStorage is synchronous but this service wraps it in Promises for consistency
20
+ * - Data is scoped to the origin (protocol + domain + port)
21
+ * - Users can clear localStorage through browser settings
22
+ *
23
+ * @returns A StorageService backed by browser localStorage
24
+ *
25
+ * @example
26
+ * ```typescript
27
+ * import { createLocalStorageService } from '@uploadista/client-browser';
28
+ *
29
+ * const storage = createLocalStorageService();
30
+ *
31
+ * // Store upload state
32
+ * await storage.setItem('upload:123', JSON.stringify({
33
+ * fileId: '123',
34
+ * progress: 75,
35
+ * uploadedChunks: [0, 1, 2]
36
+ * }));
37
+ *
38
+ * // Retrieve upload state
39
+ * const data = await storage.getItem('upload:123');
40
+ * if (data) {
41
+ * const state = JSON.parse(data);
42
+ * console.log('Resuming upload at', state.progress, '%');
43
+ * }
44
+ *
45
+ * // Find all uploads
46
+ * const uploads = await storage.find('upload:');
47
+ * console.log('Found', Object.keys(uploads).length, 'uploads');
48
+ *
49
+ * // Clean up completed upload
50
+ * await storage.removeItem('upload:123');
51
+ * ```
52
+ *
53
+ * @see {@link createSessionStorageService} for session-only storage
54
+ */
55
+ export function createLocalStorageService(): StorageService {
56
+ /**
57
+ * Internal helper to find entries matching a prefix.
58
+ *
59
+ * Iterates through all localStorage keys and returns those that start
60
+ * with the specified prefix along with their values.
61
+ *
62
+ * @param prefix - Key prefix to filter by
63
+ * @returns Object mapping matching keys to their values
64
+ * @private
65
+ */
66
+ const findEntries = (prefix: string): Record<string, string> => {
67
+ const results: Record<string, string> = {};
68
+
69
+ for (const key in localStorage) {
70
+ if (key.startsWith(prefix)) {
71
+ const item = localStorage.getItem(key);
72
+ if (item) {
73
+ results[key] = item;
74
+ }
75
+ }
76
+ }
77
+
78
+ return results;
79
+ };
80
+
81
+ return {
82
+ /**
83
+ * Retrieves a value from localStorage by key.
84
+ *
85
+ * @param key - The key to retrieve
86
+ * @returns Promise resolving to the value, or null if the key doesn't exist
87
+ *
88
+ * @example
89
+ * ```typescript
90
+ * const value = await storage.getItem('user:preferences');
91
+ * if (value) {
92
+ * const prefs = JSON.parse(value);
93
+ * }
94
+ * ```
95
+ */
96
+ async getItem(key: string): Promise<string | null> {
97
+ return localStorage.getItem(key);
98
+ },
99
+
100
+ /**
101
+ * Stores a value in localStorage.
102
+ *
103
+ * If the key already exists, its value will be overwritten.
104
+ * Values must be strings; use JSON.stringify() for objects.
105
+ *
106
+ * @param key - The key to store under
107
+ * @param value - The string value to store
108
+ *
109
+ * @throws {QuotaExceededError} If localStorage quota is exceeded
110
+ *
111
+ * @example
112
+ * ```typescript
113
+ * // Store string
114
+ * await storage.setItem('upload:status', 'completed');
115
+ *
116
+ * // Store object
117
+ * await storage.setItem('upload:metadata', JSON.stringify({
118
+ * name: 'file.txt',
119
+ * size: 1024
120
+ * }));
121
+ * ```
122
+ */
123
+ async setItem(key: string, value: string): Promise<void> {
124
+ localStorage.setItem(key, value);
125
+ },
126
+
127
+ /**
128
+ * Removes a value from localStorage by key.
129
+ *
130
+ * If the key doesn't exist, this is a no-op (no error is thrown).
131
+ *
132
+ * @param key - The key to remove
133
+ *
134
+ * @example
135
+ * ```typescript
136
+ * // Clean up completed upload
137
+ * await storage.removeItem('upload:123');
138
+ * ```
139
+ */
140
+ async removeItem(key: string): Promise<void> {
141
+ localStorage.removeItem(key);
142
+ },
143
+
144
+ /**
145
+ * Retrieves all entries from localStorage.
146
+ *
147
+ * Returns an object mapping every key in localStorage to its value.
148
+ * Use with caution as this can return a large amount of data.
149
+ *
150
+ * @returns Promise resolving to object with all key-value pairs
151
+ *
152
+ * @example
153
+ * ```typescript
154
+ * const all = await storage.findAll();
155
+ * console.log('Total items in storage:', Object.keys(all).length);
156
+ * ```
157
+ */
158
+ async findAll(): Promise<Record<string, string>> {
159
+ return findEntries("");
160
+ },
161
+
162
+ /**
163
+ * Finds all entries with keys starting with a given prefix.
164
+ *
165
+ * Useful for querying related data or implementing namespacing.
166
+ * For example, use "upload:" prefix to find all upload-related entries.
167
+ *
168
+ * @param prefix - The key prefix to search for
169
+ * @returns Promise resolving to object with matching key-value pairs
170
+ *
171
+ * @example
172
+ * ```typescript
173
+ * // Find all uploads
174
+ * const uploads = await storage.find('upload:');
175
+ * for (const [key, value] of Object.entries(uploads)) {
176
+ * console.log('Upload:', key, JSON.parse(value));
177
+ * }
178
+ *
179
+ * // Find user preferences
180
+ * const prefs = await storage.find('pref:');
181
+ * ```
182
+ */
183
+ async find(prefix: string): Promise<Record<string, string>> {
184
+ return findEntries(prefix);
185
+ },
186
+ };
187
+ }
@@ -0,0 +1,188 @@
1
+ import type { StorageService } from "@uploadista/client-core";
2
+
3
+ /**
4
+ * Creates a browser storage service using sessionStorage for temporary data storage.
5
+ *
6
+ * This service provides a key-value storage interface backed by the browser's
7
+ * sessionStorage API. Unlike localStorage, data stored with sessionStorage is
8
+ * only available for the duration of the page session and is cleared when the
9
+ * browser tab or window is closed.
10
+ *
11
+ * Use cases include:
12
+ * - Temporary upload state during a session
13
+ * - One-time authentication tokens
14
+ * - Transient UI state
15
+ * - Session-specific preferences
16
+ *
17
+ * **Key differences from localStorage:**
18
+ * - Data persists only for the current browser tab/window session
19
+ * - Each tab has its own isolated sessionStorage
20
+ * - Data is cleared when the tab/window is closed
21
+ * - Page reloads preserve sessionStorage (unlike in-memory storage)
22
+ * - Same storage quota limits as localStorage (5-10MB)
23
+ *
24
+ * @returns A StorageService backed by browser sessionStorage
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * import { createSessionStorageService } from '@uploadista/client-browser';
29
+ *
30
+ * const storage = createSessionStorageService();
31
+ *
32
+ * // Store temporary upload state
33
+ * await storage.setItem('temp-upload:abc', JSON.stringify({
34
+ * fileId: 'abc',
35
+ * started: Date.now()
36
+ * }));
37
+ *
38
+ * // Retrieve within same session
39
+ * const data = await storage.getItem('temp-upload:abc');
40
+ * if (data) {
41
+ * const state = JSON.parse(data);
42
+ * console.log('Upload started at', new Date(state.started));
43
+ * }
44
+ *
45
+ * // Find all temporary uploads
46
+ * const tempUploads = await storage.find('temp-upload:');
47
+ *
48
+ * // Clean up
49
+ * await storage.removeItem('temp-upload:abc');
50
+ * // OR: Close tab/window to clear all sessionStorage
51
+ * ```
52
+ *
53
+ * @see {@link createLocalStorageService} for persistent storage
54
+ */
55
+ export function createSessionStorageService(): StorageService {
56
+ /**
57
+ * Internal helper to find entries matching a prefix.
58
+ *
59
+ * Iterates through all sessionStorage keys and returns those that start
60
+ * with the specified prefix along with their values.
61
+ *
62
+ * @param prefix - Key prefix to filter by
63
+ * @returns Object mapping matching keys to their values
64
+ * @private
65
+ */
66
+ const findEntries = (prefix: string): Record<string, string> => {
67
+ const results: Record<string, string> = {};
68
+
69
+ for (const key in sessionStorage) {
70
+ if (key.startsWith(prefix)) {
71
+ const item = sessionStorage.getItem(key);
72
+ if (item) {
73
+ results[key] = item;
74
+ }
75
+ }
76
+ }
77
+
78
+ return results;
79
+ };
80
+
81
+ return {
82
+ /**
83
+ * Retrieves a value from sessionStorage by key.
84
+ *
85
+ * @param key - The key to retrieve
86
+ * @returns Promise resolving to the value, or null if the key doesn't exist
87
+ *
88
+ * @example
89
+ * ```typescript
90
+ * const token = await storage.getItem('session:auth-token');
91
+ * if (token) {
92
+ * // Use token for requests
93
+ * }
94
+ * ```
95
+ */
96
+ async getItem(key: string): Promise<string | null> {
97
+ return sessionStorage.getItem(key);
98
+ },
99
+
100
+ /**
101
+ * Stores a value in sessionStorage.
102
+ *
103
+ * If the key already exists, its value will be overwritten.
104
+ * Values must be strings; use JSON.stringify() for objects.
105
+ * Data will be cleared when the browser tab/window is closed.
106
+ *
107
+ * @param key - The key to store under
108
+ * @param value - The string value to store
109
+ *
110
+ * @throws {QuotaExceededError} If sessionStorage quota is exceeded
111
+ *
112
+ * @example
113
+ * ```typescript
114
+ * // Store temporary state
115
+ * await storage.setItem('wizard:step', '2');
116
+ *
117
+ * // Store temporary object
118
+ * await storage.setItem('temp:upload', JSON.stringify({
119
+ * progress: 50,
120
+ * paused: false
121
+ * }));
122
+ * ```
123
+ */
124
+ async setItem(key: string, value: string): Promise<void> {
125
+ sessionStorage.setItem(key, value);
126
+ },
127
+
128
+ /**
129
+ * Removes a value from sessionStorage by key.
130
+ *
131
+ * If the key doesn't exist, this is a no-op (no error is thrown).
132
+ *
133
+ * @param key - The key to remove
134
+ *
135
+ * @example
136
+ * ```typescript
137
+ * // Clean up temporary data
138
+ * await storage.removeItem('temp:upload:123');
139
+ * ```
140
+ */
141
+ async removeItem(key: string): Promise<void> {
142
+ sessionStorage.removeItem(key);
143
+ },
144
+
145
+ /**
146
+ * Retrieves all entries from sessionStorage.
147
+ *
148
+ * Returns an object mapping every key in sessionStorage to its value.
149
+ * This only includes data for the current tab/window.
150
+ *
151
+ * @returns Promise resolving to object with all key-value pairs
152
+ *
153
+ * @example
154
+ * ```typescript
155
+ * const all = await storage.findAll();
156
+ * console.log('Session items:', Object.keys(all).length);
157
+ * ```
158
+ */
159
+ async findAll(): Promise<Record<string, string>> {
160
+ return findEntries("");
161
+ },
162
+
163
+ /**
164
+ * Finds all entries with keys starting with a given prefix.
165
+ *
166
+ * Useful for querying related session data. For example, use "temp:"
167
+ * prefix to find all temporary entries.
168
+ *
169
+ * @param prefix - The key prefix to search for
170
+ * @returns Promise resolving to object with matching key-value pairs
171
+ *
172
+ * @example
173
+ * ```typescript
174
+ * // Find all temporary uploads in this session
175
+ * const tempUploads = await storage.find('temp-upload:');
176
+ * for (const [key, value] of Object.entries(tempUploads)) {
177
+ * console.log('Temp upload:', key, JSON.parse(value));
178
+ * }
179
+ *
180
+ * // Find wizard state
181
+ * const wizardState = await storage.find('wizard:');
182
+ * ```
183
+ */
184
+ async find(prefix: string): Promise<Record<string, string>> {
185
+ return findEntries(prefix);
186
+ },
187
+ };
188
+ }