pure-md5 0.2.0 → 0.2.1

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 (158) hide show
  1. package/dist/adapters/ie11.cjs +1 -2
  2. package/dist/adapters/ie11.js +1 -2
  3. package/dist/adapters/node.cjs +1 -2
  4. package/dist/adapters/node.js +1 -2
  5. package/dist/adapters/webcrypto.cjs +1 -2
  6. package/dist/adapters/webcrypto.js +1 -2
  7. package/dist/core/index.cjs +1 -2
  8. package/dist/core/index.js +1 -2
  9. package/dist/index.cjs +1 -2
  10. package/dist/index.js +1 -2
  11. package/dist/stream/adapter.cjs +1 -2
  12. package/dist/stream/adapter.js +1 -2
  13. package/dist/stream/fs-utils.cjs +1 -2
  14. package/dist/stream/fs-utils.js +1 -2
  15. package/dist/stream/index.cjs +1 -2
  16. package/dist/stream/index.js +1 -2
  17. package/dist/stream/light/index.cjs +1 -2
  18. package/dist/stream/light/index.js +1 -2
  19. package/dist/stream/md5-stream.cjs +1 -2
  20. package/dist/stream/md5-stream.js +1 -2
  21. package/dist/stream/whatwg-stream.cjs +1 -2
  22. package/dist/stream/whatwg-stream.js +1 -2
  23. package/dist/utils/detect.cjs +1 -2
  24. package/dist/utils/detect.js +1 -2
  25. package/package.json +1 -1
  26. package/pure-md5-0.2.0.tgz +0 -0
  27. package/.aliases +0 -19
  28. package/.bash_profile +0 -12
  29. package/.bash_prompt +0 -56
  30. package/.changeset/README.md +0 -32
  31. package/.changeset/config.json +0 -16
  32. package/.continue/mcpServers/new-mcp-server.yaml +0 -10
  33. package/.continue/rules +0 -29
  34. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -35
  35. package/.github/ISSUE_TEMPLATE/documentation.md +0 -20
  36. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
  37. package/.github/PULL_REQUEST_TEMPLATE.md +0 -35
  38. package/.github/workflows/npm-publish.yml +0 -33
  39. package/.github/workflows/release.yml +0 -42
  40. package/CHANGELOG.md +0 -9
  41. package/CONTRIBUTING.md +0 -203
  42. package/MIGRATION_GUIDE_STREAMS.md +0 -374
  43. package/STREAM_API.md +0 -582
  44. package/STREAM_BENCHMARKS.md +0 -232
  45. package/STREAM_EXAMPLES.md +0 -669
  46. package/STREAM_OPTIMIZATION_REPORT.md +0 -136
  47. package/STREAM_TROUBLESHOOTING.md +0 -537
  48. package/WEB_CRYPTO_TESTS_SUMMARY.md +0 -140
  49. package/WHATWG_STREAMS.md +0 -191
  50. package/__tests__/adapters/node-crypto.test.ts +0 -167
  51. package/__tests__/adapters/web-crypto-node.test.ts +0 -73
  52. package/__tests__/adapters/web-crypto.test.ts +0 -195
  53. package/__tests__/add32.test.ts +0 -33
  54. package/__tests__/fallback.test.ts +0 -345
  55. package/__tests__/hex.test.ts +0 -38
  56. package/__tests__/hex_chr.test.ts +0 -20
  57. package/__tests__/index.test.ts +0 -87
  58. package/__tests__/integration/fixtures/test-file.txt +0 -1
  59. package/__tests__/integration/md5-stream-file.test.ts +0 -293
  60. package/__tests__/integration/node-crypto-file.test.ts +0 -86
  61. package/__tests__/integration/web-crypto.test.ts +0 -38
  62. package/__tests__/md51.test.ts +0 -73
  63. package/__tests__/md5block.test.ts +0 -61
  64. package/__tests__/md5cycle.test.ts +0 -48
  65. package/__tests__/round-functions.test.ts +0 -87
  66. package/__tests__/stream/fs-utils.test.ts +0 -209
  67. package/__tests__/stream/md5-stream-edge-cases.test.ts +0 -461
  68. package/__tests__/stream/md5-stream.test.ts +0 -418
  69. package/__tests__/stream/whatwg-stream.test.ts +0 -355
  70. package/__tests__/stream/whatwg-stream.test.ts.bak2 +0 -335
  71. package/benchmarks/md5-stream.bench.ts +0 -212
  72. package/benchmarks/whatwg-stream.bench.ts +0 -180
  73. package/dist/adapters/ie11.cjs.map +0 -1
  74. package/dist/adapters/ie11.js.map +0 -1
  75. package/dist/adapters/node.cjs.map +0 -1
  76. package/dist/adapters/node.js.map +0 -1
  77. package/dist/adapters/webcrypto.cjs.map +0 -1
  78. package/dist/adapters/webcrypto.js.map +0 -1
  79. package/dist/chunk-2YXXFGBV.js +0 -2
  80. package/dist/chunk-2YXXFGBV.js.map +0 -1
  81. package/dist/chunk-4KSCMS4Q.js +0 -2
  82. package/dist/chunk-4KSCMS4Q.js.map +0 -1
  83. package/dist/chunk-6P2QV5SR.js +0 -4
  84. package/dist/chunk-6P2QV5SR.js.map +0 -1
  85. package/dist/chunk-G5WHEAIQ.js +0 -2
  86. package/dist/chunk-G5WHEAIQ.js.map +0 -1
  87. package/dist/chunk-H2K353LR.js +0 -2
  88. package/dist/chunk-H2K353LR.js.map +0 -1
  89. package/dist/chunk-JKVD5LHZ.js +0 -2
  90. package/dist/chunk-JKVD5LHZ.js.map +0 -1
  91. package/dist/chunk-NWQ4N5RX.js +0 -2
  92. package/dist/chunk-NWQ4N5RX.js.map +0 -1
  93. package/dist/chunk-PHZ7FTYF.js +0 -2
  94. package/dist/chunk-PHZ7FTYF.js.map +0 -1
  95. package/dist/chunk-PNZTVQA7.js +0 -2
  96. package/dist/chunk-PNZTVQA7.js.map +0 -1
  97. package/dist/chunk-R4JB5MBR.js +0 -2
  98. package/dist/chunk-R4JB5MBR.js.map +0 -1
  99. package/dist/chunk-VFOAY6XI.js +0 -2
  100. package/dist/chunk-VFOAY6XI.js.map +0 -1
  101. package/dist/chunk-XB5BQIEX.js +0 -2
  102. package/dist/chunk-XB5BQIEX.js.map +0 -1
  103. package/dist/core/index.cjs.map +0 -1
  104. package/dist/core/index.js.map +0 -1
  105. package/dist/index.cjs.map +0 -1
  106. package/dist/index.js.map +0 -1
  107. package/dist/stream/adapter.cjs.map +0 -1
  108. package/dist/stream/adapter.js.map +0 -1
  109. package/dist/stream/fs-utils.cjs.map +0 -1
  110. package/dist/stream/fs-utils.js.map +0 -1
  111. package/dist/stream/index.cjs.map +0 -1
  112. package/dist/stream/index.js.map +0 -1
  113. package/dist/stream/light/index.cjs.map +0 -1
  114. package/dist/stream/light/index.js.map +0 -1
  115. package/dist/stream/md5-stream.cjs.map +0 -1
  116. package/dist/stream/md5-stream.js.map +0 -1
  117. package/dist/stream/whatwg-stream.cjs.map +0 -1
  118. package/dist/stream/whatwg-stream.js.map +0 -1
  119. package/dist/utils/detect.cjs.map +0 -1
  120. package/dist/utils/detect.js.map +0 -1
  121. package/planning/03-optimization-size-tree-shaking/01-es-modules-tree-shaking.md +0 -152
  122. package/planning/03-optimization-size-tree-shaking/02-consolidate-modules.md +0 -65
  123. package/planning/03-optimization-size-tree-shaking/03-remove-duplicate-add32.md +0 -93
  124. package/planning/03-optimization-size-tree-shaking/04-remove-runtime-check.md +0 -102
  125. package/planning/03-optimization-size-tree-shaking/05-optimize-loops-performance.md +0 -107
  126. package/planning/03-optimization-size-tree-shaking/06-tsup-formats-configuration.md +0 -227
  127. package/planning/03-optimization-size-tree-shaking/07-multiple-build-formats.md +0 -228
  128. package/planning/03-optimization-size-tree-shaking/08-benchmarks-metrics.md +0 -34
  129. package/planning/03-optimization-size-tree-shaking/MIGRATION_GUIDE.md +0 -260
  130. package/planning/03-optimization-size-tree-shaking/README.md +0 -173
  131. package/planning/03-optimization-size-tree-shaking/SUMMARY.md +0 -168
  132. package/planning/04-adapter-backend/03-backend-web-crypto.md +0 -149
  133. package/planning/04-adapter-backend/04-backend-node-crypto.md +0 -181
  134. package/planning/04-adapter-backend/05-backend-pure-js.md +0 -174
  135. package/planning/04-adapter-backend/06-backend-ie11.md +0 -158
  136. package/planning/04-adapter-backend/07-detection-environment.md +0 -232
  137. package/planning/04-adapter-backend/08-detection-backend.md +0 -210
  138. package/planning/04-adapter-backend/09-adapter-unified.md +0 -255
  139. package/planning/04-adapter-backend/10-fallback-mechanism.md +0 -333
  140. package/planning/04-adapter-backend/11-tests-backend-web-crypto.md +0 -191
  141. package/planning/04-adapter-backend/12-tests-backend-node-crypto.md +0 -222
  142. package/planning/04-adapter-backend/README.md +0 -45
  143. package/planning/05-documentation-publishing/01-README-optimization.md +0 -105
  144. package/planning/05-documentation-publishing/02-VitePress-site-evaluation.md +0 -136
  145. package/planning/05-documentation-publishing/03-Changeset-setup.md +0 -192
  146. package/planning/05-documentation-publishing/04-GitHub-templates.md +0 -252
  147. package/planning/05-documentation-publishing/README.md +0 -22
  148. package/planning/05-documentation-publishing/STATUS.md +0 -222
  149. package/planning/prd.md +0 -405
  150. package/planning/streams/01-create-md5stream-class.md +0 -69
  151. package/planning/streams/02-create-factory-api.md +0 -65
  152. package/planning/streams/03-fs-integration.md +0 -37
  153. package/planning/streams/04-whatwg-streams-support.md +0 -37
  154. package/planning/streams/05-audit-optimization.md +0 -121
  155. package/planning/streams/06-comprehensive-tests-docs.md +0 -137
  156. package/planning/streams/07-architecture-integration.md +0 -38
  157. package/planning/streams/README.md +0 -98
  158. 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