pure-md5 0.2.0 → 0.2.2

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 (177) hide show
  1. package/README.md +38 -24
  2. package/dist/adapters/ie11.cjs +1 -2
  3. package/dist/adapters/ie11.js +1 -2
  4. package/dist/adapters/node.cjs +1 -2
  5. package/dist/adapters/node.js +1 -2
  6. package/dist/adapters/webcrypto.cjs +1 -2
  7. package/dist/adapters/webcrypto.js +1 -2
  8. package/dist/index.cjs +1 -2
  9. package/dist/index.d.ts +149 -5
  10. package/dist/index.js +3 -2
  11. package/dist/md5.cjs +1 -0
  12. package/dist/md5.d.ts +20 -0
  13. package/dist/md5.js +1 -0
  14. package/dist/stream/md5-stream.cjs +1 -2
  15. package/dist/stream/md5-stream.js +1 -2
  16. package/dist/stream/whatwg-stream.cjs +1 -2
  17. package/dist/stream/whatwg-stream.js +1 -2
  18. package/dist/utils/detect.cjs +1 -2
  19. package/dist/utils/detect.js +3 -2
  20. package/package.json +10 -15
  21. package/pure-md5-0.2.1.tgz +0 -0
  22. package/test-tree-shake.mjs +12 -0
  23. package/.aliases +0 -19
  24. package/.bash_profile +0 -12
  25. package/.bash_prompt +0 -56
  26. package/.changeset/README.md +0 -32
  27. package/.changeset/config.json +0 -16
  28. package/.continue/mcpServers/new-mcp-server.yaml +0 -10
  29. package/.continue/rules +0 -29
  30. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -35
  31. package/.github/ISSUE_TEMPLATE/documentation.md +0 -20
  32. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
  33. package/.github/PULL_REQUEST_TEMPLATE.md +0 -35
  34. package/.github/workflows/npm-publish.yml +0 -33
  35. package/.github/workflows/release.yml +0 -42
  36. package/CHANGELOG.md +0 -9
  37. package/CONTRIBUTING.md +0 -203
  38. package/MIGRATION_GUIDE_STREAMS.md +0 -374
  39. package/STREAM_API.md +0 -582
  40. package/STREAM_BENCHMARKS.md +0 -232
  41. package/STREAM_EXAMPLES.md +0 -669
  42. package/STREAM_OPTIMIZATION_REPORT.md +0 -136
  43. package/STREAM_TROUBLESHOOTING.md +0 -537
  44. package/WEB_CRYPTO_TESTS_SUMMARY.md +0 -140
  45. package/WHATWG_STREAMS.md +0 -191
  46. package/__tests__/adapters/node-crypto.test.ts +0 -167
  47. package/__tests__/adapters/web-crypto-node.test.ts +0 -73
  48. package/__tests__/adapters/web-crypto.test.ts +0 -195
  49. package/__tests__/add32.test.ts +0 -33
  50. package/__tests__/fallback.test.ts +0 -345
  51. package/__tests__/hex.test.ts +0 -38
  52. package/__tests__/hex_chr.test.ts +0 -20
  53. package/__tests__/index.test.ts +0 -87
  54. package/__tests__/integration/fixtures/test-file.txt +0 -1
  55. package/__tests__/integration/md5-stream-file.test.ts +0 -293
  56. package/__tests__/integration/node-crypto-file.test.ts +0 -86
  57. package/__tests__/integration/web-crypto.test.ts +0 -38
  58. package/__tests__/md51.test.ts +0 -73
  59. package/__tests__/md5block.test.ts +0 -61
  60. package/__tests__/md5cycle.test.ts +0 -48
  61. package/__tests__/round-functions.test.ts +0 -87
  62. package/__tests__/stream/fs-utils.test.ts +0 -209
  63. package/__tests__/stream/md5-stream-edge-cases.test.ts +0 -461
  64. package/__tests__/stream/md5-stream.test.ts +0 -418
  65. package/__tests__/stream/whatwg-stream.test.ts +0 -355
  66. package/__tests__/stream/whatwg-stream.test.ts.bak2 +0 -335
  67. package/benchmarks/md5-stream.bench.ts +0 -212
  68. package/benchmarks/whatwg-stream.bench.ts +0 -180
  69. package/dist/adapters/ie11.cjs.map +0 -1
  70. package/dist/adapters/ie11.js.map +0 -1
  71. package/dist/adapters/node.cjs.map +0 -1
  72. package/dist/adapters/node.js.map +0 -1
  73. package/dist/adapters/webcrypto.cjs.map +0 -1
  74. package/dist/adapters/webcrypto.js.map +0 -1
  75. package/dist/chunk-2YXXFGBV.js +0 -2
  76. package/dist/chunk-2YXXFGBV.js.map +0 -1
  77. package/dist/chunk-4KSCMS4Q.js +0 -2
  78. package/dist/chunk-4KSCMS4Q.js.map +0 -1
  79. package/dist/chunk-6P2QV5SR.js +0 -4
  80. package/dist/chunk-6P2QV5SR.js.map +0 -1
  81. package/dist/chunk-G5WHEAIQ.js +0 -2
  82. package/dist/chunk-G5WHEAIQ.js.map +0 -1
  83. package/dist/chunk-H2K353LR.js +0 -2
  84. package/dist/chunk-H2K353LR.js.map +0 -1
  85. package/dist/chunk-JKVD5LHZ.js +0 -2
  86. package/dist/chunk-JKVD5LHZ.js.map +0 -1
  87. package/dist/chunk-NWQ4N5RX.js +0 -2
  88. package/dist/chunk-NWQ4N5RX.js.map +0 -1
  89. package/dist/chunk-PHZ7FTYF.js +0 -2
  90. package/dist/chunk-PHZ7FTYF.js.map +0 -1
  91. package/dist/chunk-PNZTVQA7.js +0 -2
  92. package/dist/chunk-PNZTVQA7.js.map +0 -1
  93. package/dist/chunk-R4JB5MBR.js +0 -2
  94. package/dist/chunk-R4JB5MBR.js.map +0 -1
  95. package/dist/chunk-VFOAY6XI.js +0 -2
  96. package/dist/chunk-VFOAY6XI.js.map +0 -1
  97. package/dist/chunk-XB5BQIEX.js +0 -2
  98. package/dist/chunk-XB5BQIEX.js.map +0 -1
  99. package/dist/core/index.cjs +0 -2
  100. package/dist/core/index.cjs.map +0 -1
  101. package/dist/core/index.d.cts +0 -19
  102. package/dist/core/index.d.ts +0 -19
  103. package/dist/core/index.js +0 -2
  104. package/dist/core/index.js.map +0 -1
  105. package/dist/index.cjs.map +0 -1
  106. package/dist/index.d.cts +0 -84
  107. package/dist/index.js.map +0 -1
  108. package/dist/stream/adapter.cjs +0 -2
  109. package/dist/stream/adapter.cjs.map +0 -1
  110. package/dist/stream/adapter.d.cts +0 -63
  111. package/dist/stream/adapter.d.ts +0 -63
  112. package/dist/stream/adapter.js +0 -2
  113. package/dist/stream/adapter.js.map +0 -1
  114. package/dist/stream/fs-utils.cjs +0 -2
  115. package/dist/stream/fs-utils.cjs.map +0 -1
  116. package/dist/stream/fs-utils.d.cts +0 -137
  117. package/dist/stream/fs-utils.d.ts +0 -137
  118. package/dist/stream/fs-utils.js +0 -2
  119. package/dist/stream/fs-utils.js.map +0 -1
  120. package/dist/stream/index.cjs +0 -2
  121. package/dist/stream/index.cjs.map +0 -1
  122. package/dist/stream/index.d.cts +0 -4
  123. package/dist/stream/index.d.ts +0 -4
  124. package/dist/stream/index.js +0 -2
  125. package/dist/stream/index.js.map +0 -1
  126. package/dist/stream/light/index.cjs +0 -2
  127. package/dist/stream/light/index.cjs.map +0 -1
  128. package/dist/stream/light/index.d.cts +0 -4
  129. package/dist/stream/light/index.d.ts +0 -4
  130. package/dist/stream/light/index.js +0 -2
  131. package/dist/stream/light/index.js.map +0 -1
  132. package/dist/stream/md5-stream.cjs.map +0 -1
  133. package/dist/stream/md5-stream.js.map +0 -1
  134. package/dist/stream/whatwg-stream.cjs.map +0 -1
  135. package/dist/stream/whatwg-stream.js.map +0 -1
  136. package/dist/types-edGoGJ5V.d.cts +0 -42
  137. package/dist/types-edGoGJ5V.d.ts +0 -42
  138. package/dist/utils/detect.cjs.map +0 -1
  139. package/dist/utils/detect.js.map +0 -1
  140. package/planning/03-optimization-size-tree-shaking/01-es-modules-tree-shaking.md +0 -152
  141. package/planning/03-optimization-size-tree-shaking/02-consolidate-modules.md +0 -65
  142. package/planning/03-optimization-size-tree-shaking/03-remove-duplicate-add32.md +0 -93
  143. package/planning/03-optimization-size-tree-shaking/04-remove-runtime-check.md +0 -102
  144. package/planning/03-optimization-size-tree-shaking/05-optimize-loops-performance.md +0 -107
  145. package/planning/03-optimization-size-tree-shaking/06-tsup-formats-configuration.md +0 -227
  146. package/planning/03-optimization-size-tree-shaking/07-multiple-build-formats.md +0 -228
  147. package/planning/03-optimization-size-tree-shaking/08-benchmarks-metrics.md +0 -34
  148. package/planning/03-optimization-size-tree-shaking/MIGRATION_GUIDE.md +0 -260
  149. package/planning/03-optimization-size-tree-shaking/README.md +0 -173
  150. package/planning/03-optimization-size-tree-shaking/SUMMARY.md +0 -168
  151. package/planning/04-adapter-backend/03-backend-web-crypto.md +0 -149
  152. package/planning/04-adapter-backend/04-backend-node-crypto.md +0 -181
  153. package/planning/04-adapter-backend/05-backend-pure-js.md +0 -174
  154. package/planning/04-adapter-backend/06-backend-ie11.md +0 -158
  155. package/planning/04-adapter-backend/07-detection-environment.md +0 -232
  156. package/planning/04-adapter-backend/08-detection-backend.md +0 -210
  157. package/planning/04-adapter-backend/09-adapter-unified.md +0 -255
  158. package/planning/04-adapter-backend/10-fallback-mechanism.md +0 -333
  159. package/planning/04-adapter-backend/11-tests-backend-web-crypto.md +0 -191
  160. package/planning/04-adapter-backend/12-tests-backend-node-crypto.md +0 -222
  161. package/planning/04-adapter-backend/README.md +0 -45
  162. package/planning/05-documentation-publishing/01-README-optimization.md +0 -105
  163. package/planning/05-documentation-publishing/02-VitePress-site-evaluation.md +0 -136
  164. package/planning/05-documentation-publishing/03-Changeset-setup.md +0 -192
  165. package/planning/05-documentation-publishing/04-GitHub-templates.md +0 -252
  166. package/planning/05-documentation-publishing/README.md +0 -22
  167. package/planning/05-documentation-publishing/STATUS.md +0 -222
  168. package/planning/prd.md +0 -405
  169. package/planning/streams/01-create-md5stream-class.md +0 -69
  170. package/planning/streams/02-create-factory-api.md +0 -65
  171. package/planning/streams/03-fs-integration.md +0 -37
  172. package/planning/streams/04-whatwg-streams-support.md +0 -37
  173. package/planning/streams/05-audit-optimization.md +0 -121
  174. package/planning/streams/06-comprehensive-tests-docs.md +0 -137
  175. package/planning/streams/07-architecture-integration.md +0 -38
  176. package/planning/streams/README.md +0 -98
  177. package/tsup.config.ts +0 -24
package/STREAM_API.md DELETED
@@ -1,582 +0,0 @@
1
- # Streaming API Documentation
2
-
3
- ## Overview
4
-
5
- The `pure-md5` library provides comprehensive streaming support for hashing large files and data streams. This includes both Node.js Streams and WHATWG Streams (for browser environments).
6
-
7
- ## Node.js Streams API
8
-
9
- ### MD5Stream Class
10
-
11
- A Node.js Transform stream for computing MD5 hashes while processing data.
12
-
13
- #### Constructor
14
-
15
- ```typescript
16
- new MD5Stream(options?: MD5StreamOptions)
17
- ```
18
-
19
- **Parameters:**
20
-
21
- - `options` (optional): Stream options
22
- - `add32` (optional): Custom add32 function for testing/compatibility
23
-
24
- **Example:**
25
-
26
- ```typescript
27
- import { MD5Stream } from 'pure-md5';
28
- import fs from 'fs';
29
-
30
- const stream = new MD5Stream();
31
- stream.on('md5', (result) => {
32
- console.log('MD5:', result.digest);
33
- console.log('Bytes:', result.bytesProcessed);
34
- });
35
-
36
- fs.createReadStream('file.txt').pipe(stream);
37
- ```
38
-
39
- #### Events
40
-
41
- **`md5` Event**
42
-
43
- Emitted when MD5 computation is complete.
44
-
45
- ```typescript
46
- stream.on('md5', (result: MD5Result) => {
47
- console.log('MD5:', result.digest); // 32-character hex string
48
- console.log('Bytes:', result.bytesProcessed); // Total bytes processed
49
- });
50
- ```
51
-
52
- #### Methods
53
-
54
- **`getCurrentState(): { state: number[]; bytesProcessed: number }`**
55
-
56
- Get current internal MD5 state (for debugging/testing).
57
-
58
- ```typescript
59
- const stream = new MD5Stream();
60
- stream.write('test');
61
- const state = stream.getCurrentState();
62
- console.log('State:', state.state); // [1732584193, -271733879, ...]
63
- console.log('Bytes:', state.bytesProcessed); // 4
64
- ```
65
-
66
- **`getBytesProcessed(): number`**
67
-
68
- Get the total number of bytes processed so far.
69
-
70
- ```typescript
71
- const stream = new MD5Stream();
72
- stream.write('hello');
73
- console.log(stream.getBytesProcessed()); // 5
74
- ```
75
-
76
- **`reset(): void`**
77
-
78
- Reset the internal MD5 state. Allows reusing the stream instance.
79
-
80
- ```typescript
81
- const stream = new MD5Stream();
82
-
83
- // First computation
84
- stream.write('first');
85
- stream.end();
86
-
87
- // Reset and start new computation
88
- stream.reset();
89
- stream.write('second');
90
- stream.end();
91
- ```
92
-
93
- #### Static Methods
94
-
95
- **`fromStream(source: Readable, options?: MD5StreamOptions): { stream: MD5Stream; result: Promise<MD5Result> }`**
96
-
97
- Create an MD5Stream from an existing readable stream.
98
-
99
- ```typescript
100
- import { Readable } from 'stream';
101
-
102
- const source = Readable.from(['hello', ' ', 'world']);
103
- const { stream, result } = MD5Stream.fromStream(source);
104
-
105
- result.then(r => {
106
- console.log('MD5:', r.digest);
107
- console.log('Bytes:', r.bytesProcessed);
108
- });
109
- ```
110
-
111
- ### Factory Functions
112
-
113
- **`createMD5Stream(options?: MD5StreamOptions): MD5Stream`**
114
-
115
- Create a new MD5Stream instance.
116
-
117
- ```typescript
118
- import { createMD5Stream } from 'pure-md5';
119
-
120
- const stream = createMD5Stream();
121
- // Use stream...
122
- ```
123
-
124
- ### Helper Functions
125
-
126
- **`pipeThroughMD5(source: Readable, options?: MD5StreamOptions): Promise<MD5Result>`**
127
-
128
- Pipe a readable stream through an MD5 computation and return the result.
129
-
130
- ```typescript
131
- import { Readable, Transform } from 'stream';
132
- import { pipeThroughMD5 } from 'pure-md5';
133
-
134
- const source = Readable.from(['hello', ' ', 'world']);
135
- const result = await pipeThroughMD5(source);
136
-
137
- console.log('MD5:', result.digest);
138
- ```
139
-
140
- **`fromStream(source: Readable, options?: MD5StreamOptions): { stream: MD5Stream; result: Promise<MD5Result> }`**
141
-
142
- Create an MD5Stream and pipe a source through it.
143
-
144
- ```typescript
145
- import { fromStream } from 'pure-md5';
146
- import fs from 'fs';
147
-
148
- const { stream, result } = fromStream(fs.createReadStream('file.txt'));
149
-
150
- result.then(r => console.log('MD5:', r.digest));
151
- ```
152
-
153
- ### Result Type
154
-
155
- ```typescript
156
- interface MD5Result {
157
- digest: string; // MD5 hash as hex string (32 characters)
158
- bytesProcessed: number; // Total bytes processed
159
- }
160
- ```
161
-
162
- ## File System Utilities
163
-
164
- ### hashFile
165
-
166
- Async file hashing with full result.
167
-
168
- ```typescript
169
- import { hashFile } from 'pure-md5';
170
-
171
- const result = await hashFile('path/to/file.txt');
172
- console.log('MD5:', result.digest);
173
- console.log('Bytes:', result.bytesProcessed);
174
- ```
175
-
176
- **Options:**
177
-
178
- ```typescript
179
- interface HashFileOptions {
180
- add32?: (x: number, y: number) => number; // Custom add32 function
181
- }
182
- ```
183
-
184
- ### hashFileSync
185
-
186
- Synchronous file hashing (for small files).
187
-
188
- ```typescript
189
- import { hashFileSync } from 'pure-md5';
190
-
191
- const digest = hashFileSync('path/to/file.txt');
192
- console.log('MD5:', digest);
193
- ```
194
-
195
- ### hashFileDigest
196
-
197
- Get only the digest string (no bytes processed info).
198
-
199
- ```typescript
200
- import { hashFileDigest } from 'pure-md5';
201
-
202
- const digest = await hashFileDigest('path/to/file.txt');
203
- console.log('MD5:', digest);
204
- ```
205
-
206
- ### verifyFile
207
-
208
- Verify file integrity against a known hash.
209
-
210
- ```typescript
211
- import { verifyFile } from 'pure-md5';
212
-
213
- const isVerified = await verifyFile(
214
- 'path/to/file.txt',
215
- '5d41402abc4b2a76b9719d911017c592'
216
- );
217
-
218
- if (isVerified) {
219
- console.log('File verified successfully!');
220
- } else {
221
- console.log('File verification failed!');
222
- }
223
- ```
224
-
225
- ## WHATWG Streams API (Browser)
226
-
227
- ### MD5ReadableStream
228
-
229
- A wrapper for computing MD5 while reading from a ReadableStream.
230
-
231
- #### Constructor
232
-
233
- ```typescript
234
- new MD5ReadableStream(source: ReadableStream, options?: MD5ReadableStreamOptions)
235
- ```
236
-
237
- **Example:**
238
-
239
- ```typescript
240
- import { MD5ReadableStream } from 'pure-md5';
241
-
242
- const source = new ReadableStream({
243
- start(controller) {
244
- controller.enqueue(new TextEncoder().encode('Hello World'));
245
- controller.close();
246
- }
247
- });
248
-
249
- const stream = new MD5ReadableStream(source);
250
- const result = await stream.getResult();
251
- console.log('MD5:', result.digest);
252
- ```
253
-
254
- #### Methods
255
-
256
- **`getReader(): ReadableStreamDefaultReader<Uint8Array>`**
257
-
258
- Get a reader for the stream.
259
-
260
- **`getResult(): Promise<MD5Result>`**
261
-
262
- Get the MD5 result.
263
-
264
- **`getCurrentState(): { state: number[]; bytesProcessed: number }`**
265
-
266
- Get current internal state.
267
-
268
- **`getBytesProcessed(): number`**
269
-
270
- Get bytes processed so far.
271
-
272
- #### Static Methods
273
-
274
- **`hash(source: ReadableStream, options?: MD5ReadableStreamOptions): Promise<MD5Result>`**
275
-
276
- Hash a stream directly.
277
-
278
- ```typescript
279
- const result = await MD5ReadableStream.hash(source);
280
- ```
281
-
282
- **`hashFile(file: File, options?: MD5ReadableStreamOptions): Promise<MD5Result>`**
283
-
284
- Hash a File object.
285
-
286
- ```typescript
287
- const input = document.querySelector('input[type="file"]');
288
- const file = input.files[0];
289
- const result = await MD5ReadableStream.hashFile(file);
290
- ```
291
-
292
- **`hashBlob(blob: Blob, options?: MD5ReadableStreamOptions): Promise<MD5Result>`**
293
-
294
- Hash a Blob object.
295
-
296
- ```typescript
297
- const canvas = document.querySelector('canvas');
298
- canvas.toBlob(async (blob) => {
299
- const result = await MD5ReadableStream.hashBlob(blob!);
300
- console.log('MD5:', result.digest);
301
- });
302
- ```
303
-
304
- ### Factory Functions
305
-
306
- **`createMD5ReadableStream(source: ReadableStream, options?: MD5ReadableStreamOptions): MD5ReadableStream`**
307
-
308
- Create a new MD5ReadableStream instance.
309
-
310
- ### Standalone Functions
311
-
312
- **`hashReadableStream(stream: ReadableStream, options?: MD5ReadableStreamOptions): Promise<MD5Result>`**
313
-
314
- Hash a ReadableStream.
315
-
316
- **`hashFile(file: File, options?: MD5ReadableStreamOptions): Promise<MD5Result>`**
317
-
318
- Hash a File object.
319
-
320
- **`hashBlob(blob: Blob, options?: MD5ReadableStreamOptions): Promise<MD5Result>`**
321
-
322
- Hash a Blob object.
323
-
324
- **`consumeWithMD5(source: ReadableStream, options?: MD5ReadableStreamOptions): Promise<MD5Result>`**
325
-
326
- Consume a stream while computing MD5.
327
-
328
- ## Usage Examples
329
-
330
- ### Example 1: Hash a Large File
331
-
332
- ```typescript
333
- import { MD5Stream } from 'pure-md5';
334
- import fs from 'fs';
335
-
336
- const stream = new MD5Stream();
337
- let bytesProcessed = 0;
338
-
339
- stream.on('md5', (result) => {
340
- console.log('MD5:', result.digest);
341
- console.log('Total bytes:', result.bytesProcessed);
342
- });
343
-
344
- stream.on('data', (chunk) => {
345
- bytesProcessed += chunk.length;
346
- const progress = (bytesProcessed / fileSize * 100).toFixed(1);
347
- console.log(`Progress: ${progress}%`);
348
- });
349
-
350
- fs.createReadStream('large-file.bin').pipe(stream);
351
- ```
352
-
353
- ### Example 2: Browser File Upload with Progress
354
-
355
- ```typescript
356
- import { MD5ReadableStream } from 'pure-md5';
357
-
358
- async function uploadWithHash(file: File): Promise<void> {
359
- const fileStream = file.stream();
360
- const md5Stream = new MD5ReadableStream(fileStream);
361
-
362
- const reader = md5Stream.getReader();
363
- let bytesProcessed = 0;
364
-
365
- while (true) {
366
- const { done, value } = await reader.read();
367
- if (done) break;
368
-
369
- bytesProcessed += value.length;
370
- const progress = (bytesProcessed / file.size * 100).toFixed(1);
371
- console.log(`Upload progress: ${progress}%`);
372
- }
373
-
374
- const result = await md5Stream.getResult();
375
- console.log('Upload complete. MD5:', result.digest);
376
-
377
- // Upload file with hash...
378
- }
379
- ```
380
-
381
- ### Example 3: Verify Downloaded File
382
-
383
- ```typescript
384
- import { verifyFile } from 'pure-md5';
385
-
386
- async function verifyDownload(url: string, expectedHash: string): Promise<boolean> {
387
- const response = await fetch(url);
388
- const blob = await response.blob();
389
-
390
- // Create a File from Blob
391
- const file = new File([blob], 'downloaded-file.bin', { type: blob.type });
392
-
393
- const isVerified = await verifyFile(file, expectedHash);
394
- return isVerified;
395
- }
396
- ```
397
-
398
- ### Example 4: Hash Multiple Files Concurrently
399
-
400
- ```typescript
401
- import { hashFile } from 'pure-md5';
402
- import fs from 'fs';
403
-
404
- async function hashFilesConcurrently(files: string[]): Promise<Map<string, string>> {
405
- const results = new Map<string, string>();
406
-
407
- const promises = files.map(async (file) => {
408
- const result = await hashFile(file);
409
- return [file, result.digest] as const;
410
- });
411
-
412
- const resolved = await Promise.all(promises);
413
- resolved.forEach(([file, digest]) => results.set(file, digest));
414
-
415
- return results;
416
- }
417
-
418
- // Usage
419
- const fileHashes = await hashFilesConcurrently(['file1.txt', 'file2.txt', 'file3.txt']);
420
- fileHashes.forEach((hash, file) => console.log(`${file}: ${hash}`));
421
- ```
422
-
423
- ### Example 5: Streaming Data with Progress
424
-
425
- ```typescript
426
- import { MD5Stream } from 'pure-md5';
427
-
428
- async function streamWithProgress(source: NodeJS.ReadableStream): Promise<string> {
429
- return new Promise((resolve, reject) => {
430
- const stream = new MD5Stream();
431
- const totalSize = 1000000; // Known total size
432
- let processed = 0;
433
-
434
- stream.on('md5', (result) => {
435
- console.log('Complete! MD5:', result.digest);
436
- resolve(result.digest);
437
- });
438
-
439
- stream.on('data', (chunk) => {
440
- processed += chunk.length;
441
- const progress = ((processed / totalSize) * 100).toFixed(1);
442
- console.log(`Processing: ${progress}%`);
443
- });
444
-
445
- source.pipe(stream);
446
- });
447
- }
448
- ```
449
-
450
- ## Error Handling
451
-
452
- ### Node.js Streams
453
-
454
- ```typescript
455
- import { MD5Stream } from 'pure-md5';
456
-
457
- const stream = new MD5Stream();
458
-
459
- stream.on('error', (error) => {
460
- console.error('Stream error:', error.message);
461
- });
462
-
463
- stream.on('md5', (result) => {
464
- console.log('Success:', result.digest);
465
- });
466
-
467
- // Error will be caught by 'error' handler
468
- fs.createReadStream('nonexistent.txt').pipe(stream);
469
- ```
470
-
471
- ### WHATWG Streams
472
-
473
- ```typescript
474
- import { MD5ReadableStream } from 'pure-md5';
475
-
476
- try {
477
- const stream = new MD5ReadableStream(source);
478
- const result = await stream.getResult();
479
- console.log('Success:', result.digest);
480
- } catch (error) {
481
- console.error('Stream error:', error.message);
482
- }
483
- ```
484
-
485
- ## Performance Tips
486
-
487
- 1. **Use 64KB chunks** for optimal performance with Node.js streams
488
- 2. **Reuse stream instances** with `reset()` when processing multiple files
489
- 3. **For browser**, use `hashBlob()` or `hashFile()` directly for File/Blob objects
490
- 4. **Monitor memory usage** with very large files (use streaming, not full load)
491
- 5. **Consider parallel processing** for multiple independent files
492
-
493
- ## Migration Guide
494
-
495
- ### From crypto.createHash()
496
-
497
- **Before:**
498
- ```typescript
499
- import crypto from 'crypto';
500
-
501
- const hash = crypto.createHash('md5').update(data).digest('hex');
502
- ```
503
-
504
- **After:**
505
- ```typescript
506
- import { MD5Stream } from 'pure-md5';
507
-
508
- // For strings
509
- const stream = new MD5Stream();
510
- let digest = '';
511
- stream.on('md5', (result) => digest = result.digest);
512
- stream.end(data);
513
-
514
- // Or use fromStream
515
- const { result } = fromStream(Readable.from([data]));
516
- const digest = await result;
517
- ```
518
-
519
- ### From browser-based hashing
520
-
521
- **Before:**
522
- ```typescript
523
- // Manual implementation
524
- const buffer = await file.arrayBuffer();
525
- const hashBuffer = await crypto.subtle.digest('MD5', buffer);
526
- // ... convert to hex
527
- ```
528
-
529
- **After:**
530
- ```typescript
531
- import { hashFile } from 'pure-md5';
532
-
533
- const result = await hashFile(file);
534
- const digest = result.digest;
535
- ```
536
-
537
- ## Browser Compatibility
538
-
539
- WHATWG Streams API requires modern browsers:
540
- - Chrome 52+
541
- - Firefox 57+
542
- - Safari 12.1+
543
- - Edge 79+
544
-
545
- For older browsers, consider using a WHATWG Streams polyfill.
546
-
547
- ## FAQ
548
-
549
- **Q: Which API should I use for Node.js?**
550
- A: Use `MD5Stream` or the file utilities (`hashFile`, `hashFileSync`).
551
-
552
- **Q: Which API should I use in the browser?**
553
- A: Use `MD5ReadableStream` or the standalone functions (`hashFile`, `hashBlob`).
554
-
555
- **Q: How do I track progress?**
556
- A: Listen to 'data' events in Node.js or use the reader in WHATWG streams.
557
-
558
- **Q: Can I hash data that doesn't fit in memory?**
559
- A: Yes! Use streaming APIs to process data in chunks.
560
-
561
- **Q: Is the stream API thread-safe?**
562
- A: Yes, each stream instance maintains its own state.
563
-
564
- **Q: What's the difference between `fromStream` and `pipeThroughMD5`?**
565
- A: `fromStream` returns both stream and result for more control, while `pipeThroughMD5` is a convenience function that handles piping automatically.
566
-
567
- ## Performance Benchmarks
568
-
569
- See `STREAM_OPTIMIZATION_REPORT.md` for detailed performance metrics.
570
-
571
- | File Size | MD5Stream (ms) | Native (ms) | Ratio |
572
- |-----------|----------------|-------------|-------|
573
- | 1 KB | 0.15 | 0.08 | 1.88x |
574
- | 1 MB | 5.23 | 4.12 | 1.27x |
575
- | 10 MB | 48.67 | 38.45 | 1.27x |
576
- | 100 MB | 482.34 | 389.21 | 1.24x |
577
-
578
- ## See Also
579
-
580
- - [README.md](README.md) - Basic MD5 usage
581
- - [STREAM_OPTIMIZATION_REPORT.md](STREAM_OPTIMIZATION_REPORT.md) - Performance details
582
- - [WHATWG_STREAMS.md](WHATWG_STREAMS.md) - Browser streaming guide