@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,179 @@
1
+ /**
2
+ * Creates a browser storage service using sessionStorage for temporary data storage.
3
+ *
4
+ * This service provides a key-value storage interface backed by the browser's
5
+ * sessionStorage API. Unlike localStorage, data stored with sessionStorage is
6
+ * only available for the duration of the page session and is cleared when the
7
+ * browser tab or window is closed.
8
+ *
9
+ * Use cases include:
10
+ * - Temporary upload state during a session
11
+ * - One-time authentication tokens
12
+ * - Transient UI state
13
+ * - Session-specific preferences
14
+ *
15
+ * **Key differences from localStorage:**
16
+ * - Data persists only for the current browser tab/window session
17
+ * - Each tab has its own isolated sessionStorage
18
+ * - Data is cleared when the tab/window is closed
19
+ * - Page reloads preserve sessionStorage (unlike in-memory storage)
20
+ * - Same storage quota limits as localStorage (5-10MB)
21
+ *
22
+ * @returns A StorageService backed by browser sessionStorage
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * import { createSessionStorageService } from '@uploadista/client-browser';
27
+ *
28
+ * const storage = createSessionStorageService();
29
+ *
30
+ * // Store temporary upload state
31
+ * await storage.setItem('temp-upload:abc', JSON.stringify({
32
+ * fileId: 'abc',
33
+ * started: Date.now()
34
+ * }));
35
+ *
36
+ * // Retrieve within same session
37
+ * const data = await storage.getItem('temp-upload:abc');
38
+ * if (data) {
39
+ * const state = JSON.parse(data);
40
+ * console.log('Upload started at', new Date(state.started));
41
+ * }
42
+ *
43
+ * // Find all temporary uploads
44
+ * const tempUploads = await storage.find('temp-upload:');
45
+ *
46
+ * // Clean up
47
+ * await storage.removeItem('temp-upload:abc');
48
+ * // OR: Close tab/window to clear all sessionStorage
49
+ * ```
50
+ *
51
+ * @see {@link createLocalStorageService} for persistent storage
52
+ */
53
+ export function createSessionStorageService() {
54
+ /**
55
+ * Internal helper to find entries matching a prefix.
56
+ *
57
+ * Iterates through all sessionStorage keys and returns those that start
58
+ * with the specified prefix along with their values.
59
+ *
60
+ * @param prefix - Key prefix to filter by
61
+ * @returns Object mapping matching keys to their values
62
+ * @private
63
+ */
64
+ const findEntries = (prefix) => {
65
+ const results = {};
66
+ for (const key in sessionStorage) {
67
+ if (key.startsWith(prefix)) {
68
+ const item = sessionStorage.getItem(key);
69
+ if (item) {
70
+ results[key] = item;
71
+ }
72
+ }
73
+ }
74
+ return results;
75
+ };
76
+ return {
77
+ /**
78
+ * Retrieves a value from sessionStorage by key.
79
+ *
80
+ * @param key - The key to retrieve
81
+ * @returns Promise resolving to the value, or null if the key doesn't exist
82
+ *
83
+ * @example
84
+ * ```typescript
85
+ * const token = await storage.getItem('session:auth-token');
86
+ * if (token) {
87
+ * // Use token for requests
88
+ * }
89
+ * ```
90
+ */
91
+ async getItem(key) {
92
+ return sessionStorage.getItem(key);
93
+ },
94
+ /**
95
+ * Stores a value in sessionStorage.
96
+ *
97
+ * If the key already exists, its value will be overwritten.
98
+ * Values must be strings; use JSON.stringify() for objects.
99
+ * Data will be cleared when the browser tab/window is closed.
100
+ *
101
+ * @param key - The key to store under
102
+ * @param value - The string value to store
103
+ *
104
+ * @throws {QuotaExceededError} If sessionStorage quota is exceeded
105
+ *
106
+ * @example
107
+ * ```typescript
108
+ * // Store temporary state
109
+ * await storage.setItem('wizard:step', '2');
110
+ *
111
+ * // Store temporary object
112
+ * await storage.setItem('temp:upload', JSON.stringify({
113
+ * progress: 50,
114
+ * paused: false
115
+ * }));
116
+ * ```
117
+ */
118
+ async setItem(key, value) {
119
+ sessionStorage.setItem(key, value);
120
+ },
121
+ /**
122
+ * Removes a value from sessionStorage by key.
123
+ *
124
+ * If the key doesn't exist, this is a no-op (no error is thrown).
125
+ *
126
+ * @param key - The key to remove
127
+ *
128
+ * @example
129
+ * ```typescript
130
+ * // Clean up temporary data
131
+ * await storage.removeItem('temp:upload:123');
132
+ * ```
133
+ */
134
+ async removeItem(key) {
135
+ sessionStorage.removeItem(key);
136
+ },
137
+ /**
138
+ * Retrieves all entries from sessionStorage.
139
+ *
140
+ * Returns an object mapping every key in sessionStorage to its value.
141
+ * This only includes data for the current tab/window.
142
+ *
143
+ * @returns Promise resolving to object with all key-value pairs
144
+ *
145
+ * @example
146
+ * ```typescript
147
+ * const all = await storage.findAll();
148
+ * console.log('Session items:', Object.keys(all).length);
149
+ * ```
150
+ */
151
+ async findAll() {
152
+ return findEntries("");
153
+ },
154
+ /**
155
+ * Finds all entries with keys starting with a given prefix.
156
+ *
157
+ * Useful for querying related session data. For example, use "temp:"
158
+ * prefix to find all temporary entries.
159
+ *
160
+ * @param prefix - The key prefix to search for
161
+ * @returns Promise resolving to object with matching key-value pairs
162
+ *
163
+ * @example
164
+ * ```typescript
165
+ * // Find all temporary uploads in this session
166
+ * const tempUploads = await storage.find('temp-upload:');
167
+ * for (const [key, value] of Object.entries(tempUploads)) {
168
+ * console.log('Temp upload:', key, JSON.parse(value));
169
+ * }
170
+ *
171
+ * // Find wizard state
172
+ * const wizardState = await storage.find('wizard:');
173
+ * ```
174
+ */
175
+ async find(prefix) {
176
+ return findEntries(prefix);
177
+ },
178
+ };
179
+ }
@@ -0,0 +1,46 @@
1
+ import type { WebSocketFactory } from "@uploadista/client-core";
2
+ /**
3
+ * Creates a factory for browser WebSocket connections.
4
+ *
5
+ * This factory is used by the Uploadista client to create WebSocket connections
6
+ * for real-time features. It wraps the browser's native WebSocket API and provides
7
+ * a consistent interface for the client.
8
+ *
9
+ * The factory creates WebSockets that support:
10
+ * - Real-time upload progress updates
11
+ * - Flow execution status streaming
12
+ * - Live error and event notifications
13
+ * - Bidirectional client-server communication
14
+ *
15
+ * @returns A WebSocketFactory that creates browser-compatible WebSocket connections
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * import { createBrowserWebSocketFactory } from '@uploadista/client-browser';
20
+ *
21
+ * const factory = createBrowserWebSocketFactory();
22
+ *
23
+ * // Create a WebSocket connection
24
+ * const ws = factory.create('wss://api.example.com/ws/upload/123');
25
+ *
26
+ * // Set up event handlers
27
+ * ws.onmessage = (event) => {
28
+ * const data = JSON.parse(event.data);
29
+ * if (data.type === 'progress') {
30
+ * console.log('Upload progress:', data.progress);
31
+ * }
32
+ * };
33
+ *
34
+ * ws.onopen = () => {
35
+ * console.log('WebSocket connected');
36
+ * };
37
+ *
38
+ * ws.onclose = (event) => {
39
+ * console.log('WebSocket closed:', event.code, event.reason);
40
+ * };
41
+ * ```
42
+ *
43
+ * @see {@link BrowserWebSocket} for the WebSocket implementation details
44
+ */
45
+ export declare const createBrowserWebSocketFactory: () => WebSocketFactory;
46
+ //# sourceMappingURL=websocket-factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"websocket-factory.d.ts","sourceRoot":"","sources":["../../src/services/websocket-factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAiB,MAAM,yBAAyB,CAAC;AAsK/E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,eAAO,MAAM,6BAA6B,QAAO,gBAE/C,CAAC"}
@@ -0,0 +1,196 @@
1
+ /**
2
+ * Browser implementation of WebSocket that wraps the native WebSocket API.
3
+ *
4
+ * This class provides a minimal wrapper around the browser's native WebSocket
5
+ * to ensure compatibility with the Uploadista client's WebSocketLike interface.
6
+ * It's used for real-time communication features like:
7
+ * - Upload progress streaming
8
+ * - Flow execution status updates
9
+ * - Real-time error notifications
10
+ * - Live event feeds
11
+ *
12
+ * The wrapper preserves all WebSocket states and properly proxies all events
13
+ * while maintaining the standard WebSocket lifecycle.
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * const ws = new BrowserWebSocket('wss://api.example.com/ws');
18
+ *
19
+ * ws.onopen = () => {
20
+ * console.log('Connected');
21
+ * ws.send('Hello server');
22
+ * };
23
+ *
24
+ * ws.onmessage = (event) => {
25
+ * console.log('Message:', event.data);
26
+ * };
27
+ *
28
+ * ws.onerror = (event) => {
29
+ * console.error('Error:', event.message);
30
+ * };
31
+ *
32
+ * ws.onclose = (event) => {
33
+ * console.log('Closed:', event.code, event.reason);
34
+ * };
35
+ * ```
36
+ */
37
+ class BrowserWebSocket {
38
+ /** WebSocket is currently connecting (readyState = 0) */
39
+ CONNECTING = 0;
40
+ /** WebSocket connection is open and ready (readyState = 1) */
41
+ OPEN = 1;
42
+ /** WebSocket is closing (readyState = 2) */
43
+ CLOSING = 2;
44
+ /** WebSocket connection is closed (readyState = 3) */
45
+ CLOSED = 3;
46
+ /**
47
+ * Current state of the WebSocket connection.
48
+ *
49
+ * Possible values:
50
+ * - 0 (CONNECTING): Connection is being established
51
+ * - 1 (OPEN): Connection is open and ready for communication
52
+ * - 2 (CLOSING): Connection is closing
53
+ * - 3 (CLOSED): Connection is closed or couldn't be opened
54
+ */
55
+ readyState;
56
+ /** Event handler called when the connection is established */
57
+ onopen = null;
58
+ /** Event handler called when the connection is closed */
59
+ onclose = null;
60
+ /** Event handler called when an error occurs */
61
+ onerror = null;
62
+ /** Event handler called when a message is received */
63
+ onmessage = null;
64
+ native;
65
+ /**
66
+ * Creates a new BrowserWebSocket instance.
67
+ *
68
+ * Initializes a native WebSocket connection to the specified URL and sets up
69
+ * event handler proxying to convert native events to the WebSocketLike format.
70
+ *
71
+ * @param url - WebSocket URL to connect to (must use ws:// or wss:// protocol)
72
+ *
73
+ * @example
74
+ * ```typescript
75
+ * const ws = new BrowserWebSocket('wss://api.example.com/upload/progress');
76
+ * ```
77
+ */
78
+ constructor(url) {
79
+ this.native = new WebSocket(url);
80
+ this.readyState = this.native.readyState;
81
+ // Proxy event handlers to convert native events to WebSocketLike format
82
+ this.native.onopen = () => {
83
+ this.readyState = this.native.readyState;
84
+ this.onopen?.();
85
+ };
86
+ this.native.onclose = (event) => {
87
+ this.readyState = this.native.readyState;
88
+ const closeEvent = event;
89
+ this.onclose?.({ code: closeEvent.code, reason: closeEvent.reason });
90
+ };
91
+ this.native.onerror = (_event) => {
92
+ this.onerror?.({ message: "WebSocket error" });
93
+ };
94
+ this.native.onmessage = (event) => {
95
+ const messageEvent = event;
96
+ this.onmessage?.({ data: messageEvent.data });
97
+ };
98
+ }
99
+ /**
100
+ * Sends data through the WebSocket connection.
101
+ *
102
+ * The data can be either a string (text message) or a Uint8Array (binary message).
103
+ * The connection must be in the OPEN state before sending data.
104
+ *
105
+ * @param data - String or binary data to send
106
+ *
107
+ * @throws {Error} If the connection is not open
108
+ *
109
+ * @example
110
+ * ```typescript
111
+ * // Send text message
112
+ * ws.send('{"type": "subscribe", "channel": "uploads"}');
113
+ *
114
+ * // Send binary data
115
+ * const buffer = new Uint8Array([1, 2, 3, 4]);
116
+ * ws.send(buffer);
117
+ * ```
118
+ */
119
+ send(data) {
120
+ this.native.send(data);
121
+ }
122
+ /**
123
+ * Closes the WebSocket connection.
124
+ *
125
+ * Optionally accepts a close code and reason that will be sent to the server.
126
+ * Standard close codes include:
127
+ * - 1000: Normal closure
128
+ * - 1001: Going away (e.g., page navigation)
129
+ * - 1002: Protocol error
130
+ * - 1003: Unsupported data
131
+ *
132
+ * @param code - Optional close code (default: 1000 for normal closure)
133
+ * @param reason - Optional human-readable reason for closing
134
+ *
135
+ * @example
136
+ * ```typescript
137
+ * // Normal close
138
+ * ws.close();
139
+ *
140
+ * // Close with reason
141
+ * ws.close(1000, 'Upload completed');
142
+ *
143
+ * // Close due to error
144
+ * ws.close(1011, 'Internal error during upload');
145
+ * ```
146
+ */
147
+ close(code, reason) {
148
+ this.native.close(code, reason);
149
+ }
150
+ }
151
+ /**
152
+ * Creates a factory for browser WebSocket connections.
153
+ *
154
+ * This factory is used by the Uploadista client to create WebSocket connections
155
+ * for real-time features. It wraps the browser's native WebSocket API and provides
156
+ * a consistent interface for the client.
157
+ *
158
+ * The factory creates WebSockets that support:
159
+ * - Real-time upload progress updates
160
+ * - Flow execution status streaming
161
+ * - Live error and event notifications
162
+ * - Bidirectional client-server communication
163
+ *
164
+ * @returns A WebSocketFactory that creates browser-compatible WebSocket connections
165
+ *
166
+ * @example
167
+ * ```typescript
168
+ * import { createBrowserWebSocketFactory } from '@uploadista/client-browser';
169
+ *
170
+ * const factory = createBrowserWebSocketFactory();
171
+ *
172
+ * // Create a WebSocket connection
173
+ * const ws = factory.create('wss://api.example.com/ws/upload/123');
174
+ *
175
+ * // Set up event handlers
176
+ * ws.onmessage = (event) => {
177
+ * const data = JSON.parse(event.data);
178
+ * if (data.type === 'progress') {
179
+ * console.log('Upload progress:', data.progress);
180
+ * }
181
+ * };
182
+ *
183
+ * ws.onopen = () => {
184
+ * console.log('WebSocket connected');
185
+ * };
186
+ *
187
+ * ws.onclose = (event) => {
188
+ * console.log('WebSocket closed:', event.code, event.reason);
189
+ * };
190
+ * ```
191
+ *
192
+ * @see {@link BrowserWebSocket} for the WebSocket implementation details
193
+ */
194
+ export const createBrowserWebSocketFactory = () => ({
195
+ create: (url) => new BrowserWebSocket(url),
196
+ });
@@ -0,0 +1,2 @@
1
+ export * from "./upload-input";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1 @@
1
+ export * from "./upload-input";
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Browser-specific upload input types that can be used with the Uploadista client.
3
+ *
4
+ * In the browser environment, files can be provided as either:
5
+ * - `File` objects from file input elements or drag-and-drop
6
+ * - `Blob` objects created programmatically or from other sources
7
+ *
8
+ * Both types use the browser's File API and can be chunked for upload.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * // From file input
13
+ * const fileInput = document.querySelector<HTMLInputElement>('input[type="file"]');
14
+ * const file: BrowserUploadInput = fileInput.files[0];
15
+ *
16
+ * // From drag and drop
17
+ * element.addEventListener('drop', (e) => {
18
+ * const file: BrowserUploadInput = e.dataTransfer.files[0];
19
+ * });
20
+ *
21
+ * // From Blob
22
+ * const blob: BrowserUploadInput = new Blob(['content'], { type: 'text/plain' });
23
+ * ```
24
+ */
25
+ export type BrowserUploadInput = Blob | File;
26
+ //# sourceMappingURL=upload-input.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upload-input.d.ts","sourceRoot":"","sources":["../../src/types/upload-input.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,MAAM,kBAAkB,GAAG,IAAI,GAAG,IAAI,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Computes the SHA-256 checksum of a Blob using the Web Crypto API.
3
+ *
4
+ * This utility function provides a browser-native way to compute cryptographic
5
+ * hashes of file data. It uses the SubtleCrypto API (part of Web Crypto) which
6
+ * provides hardware-accelerated cryptographic operations when available.
7
+ *
8
+ * The SHA-256 algorithm produces a 256-bit (32-byte) hash value, typically
9
+ * rendered as a 64-character hexadecimal string. SHA-256 is widely used for:
10
+ * - File integrity verification
11
+ * - Content deduplication
12
+ * - File fingerprinting
13
+ * - Checksum validation
14
+ *
15
+ * **Performance note:** For large files (>100MB), this function loads the entire
16
+ * file into memory before hashing. For extremely large files, consider chunked
17
+ * hashing approaches if memory is a concern.
18
+ *
19
+ * @param blob - The Blob or File to hash
20
+ * @returns Promise resolving to the hex-encoded SHA-256 hash
21
+ *
22
+ * @throws {Error} When the hash computation fails (e.g., out of memory, crypto API unavailable)
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * import { computeblobSha256 } from '@uploadista/client-browser';
27
+ *
28
+ * // Hash a File from input
29
+ * const fileInput = document.querySelector('input[type="file"]');
30
+ * const file = fileInput.files[0];
31
+ * const hash = await computeblobSha256(file);
32
+ * console.log('File SHA-256:', hash);
33
+ * // Output: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
34
+ *
35
+ * // Hash a Blob
36
+ * const blob = new Blob(['Hello, World!'], { type: 'text/plain' });
37
+ * const hash = await computeblobSha256(blob);
38
+ * console.log('Blob SHA-256:', hash);
39
+ *
40
+ * // Verify file integrity
41
+ * const expectedHash = 'abc123...';
42
+ * const actualHash = await computeblobSha256(file);
43
+ * if (actualHash === expectedHash) {
44
+ * console.log('File integrity verified');
45
+ * } else {
46
+ * console.error('File has been modified or corrupted');
47
+ * }
48
+ *
49
+ * // Check for duplicate files
50
+ * const file1Hash = await computeblobSha256(file1);
51
+ * const file2Hash = await computeblobSha256(file2);
52
+ * if (file1Hash === file2Hash) {
53
+ * console.log('Files are identical (same content)');
54
+ * }
55
+ * ```
56
+ *
57
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest} for SubtleCrypto.digest API
58
+ */
59
+ export declare function computeblobSha256(blob: Blob): Promise<string>;
60
+ //# sourceMappingURL=hash-util.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hash-util.d.ts","sourceRoot":"","sources":["../../src/utils/hash-util.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyDG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAoBnE"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Computes the SHA-256 checksum of a Blob using the Web Crypto API.
3
+ *
4
+ * This utility function provides a browser-native way to compute cryptographic
5
+ * hashes of file data. It uses the SubtleCrypto API (part of Web Crypto) which
6
+ * provides hardware-accelerated cryptographic operations when available.
7
+ *
8
+ * The SHA-256 algorithm produces a 256-bit (32-byte) hash value, typically
9
+ * rendered as a 64-character hexadecimal string. SHA-256 is widely used for:
10
+ * - File integrity verification
11
+ * - Content deduplication
12
+ * - File fingerprinting
13
+ * - Checksum validation
14
+ *
15
+ * **Performance note:** For large files (>100MB), this function loads the entire
16
+ * file into memory before hashing. For extremely large files, consider chunked
17
+ * hashing approaches if memory is a concern.
18
+ *
19
+ * @param blob - The Blob or File to hash
20
+ * @returns Promise resolving to the hex-encoded SHA-256 hash
21
+ *
22
+ * @throws {Error} When the hash computation fails (e.g., out of memory, crypto API unavailable)
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * import { computeblobSha256 } from '@uploadista/client-browser';
27
+ *
28
+ * // Hash a File from input
29
+ * const fileInput = document.querySelector('input[type="file"]');
30
+ * const file = fileInput.files[0];
31
+ * const hash = await computeblobSha256(file);
32
+ * console.log('File SHA-256:', hash);
33
+ * // Output: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
34
+ *
35
+ * // Hash a Blob
36
+ * const blob = new Blob(['Hello, World!'], { type: 'text/plain' });
37
+ * const hash = await computeblobSha256(blob);
38
+ * console.log('Blob SHA-256:', hash);
39
+ *
40
+ * // Verify file integrity
41
+ * const expectedHash = 'abc123...';
42
+ * const actualHash = await computeblobSha256(file);
43
+ * if (actualHash === expectedHash) {
44
+ * console.log('File integrity verified');
45
+ * } else {
46
+ * console.error('File has been modified or corrupted');
47
+ * }
48
+ *
49
+ * // Check for duplicate files
50
+ * const file1Hash = await computeblobSha256(file1);
51
+ * const file2Hash = await computeblobSha256(file2);
52
+ * if (file1Hash === file2Hash) {
53
+ * console.log('Files are identical (same content)');
54
+ * }
55
+ * ```
56
+ *
57
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest} for SubtleCrypto.digest API
58
+ */
59
+ export async function computeblobSha256(blob) {
60
+ try {
61
+ // Read blob as ArrayBuffer
62
+ const arrayBuffer = await blob.arrayBuffer();
63
+ // Compute SHA-256 hash using Web Crypto API
64
+ const hashBuffer = await crypto.subtle.digest("SHA-256", arrayBuffer);
65
+ // Convert hash to hex string
66
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
67
+ const hashHex = hashArray
68
+ .map((byte) => byte.toString(16).padStart(2, "0"))
69
+ .join("");
70
+ return hashHex;
71
+ }
72
+ catch (error) {
73
+ throw new Error(`Failed to compute file checksum: ${error instanceof Error ? error.message : "Unknown error"}`);
74
+ }
75
+ }
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "@uploadista/client-browser",
3
+ "type": "module",
4
+ "version": "0.0.3",
5
+ "description": "Browser client for Uploadista",
6
+ "license": "MIT",
7
+ "author": "Uploadista",
8
+ "exports": {
9
+ ".": "./src/index.ts",
10
+ "./flow": "./src/flow/index.ts",
11
+ "./upload": "./src/upload/index.ts",
12
+ "./framework-utils": "./src/framework-utils.ts"
13
+ },
14
+ "dependencies": {
15
+ "js-base64": "3.7.8",
16
+ "@uploadista/core": "0.0.3",
17
+ "@uploadista/client-core": "0.0.3"
18
+ },
19
+ "devDependencies": {
20
+ "vitest": "3.2.4",
21
+ "@uploadista/typescript-config": "0.0.3"
22
+ },
23
+ "scripts": {
24
+ "build": "tsc -b",
25
+ "format": "biome format --write ./src",
26
+ "lint": "biome lint --write ./src",
27
+ "check": "biome check --write ./src ",
28
+ "test": "vitest",
29
+ "test:run": "vitest run",
30
+ "test:watch": "vitest --watch"
31
+ }
32
+ }