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
@@ -1,669 +0,0 @@
1
- # MD5 Streaming API - Usage Examples
2
-
3
- This document provides practical examples for using the MD5 streaming API in various scenarios.
4
-
5
- ## Table of Contents
6
-
7
- 1. [Basic Usage](#basic-usage)
8
- 2. [File Operations](#file-operations)
9
- 3. [Browser Usage](#browser-usage)
10
- 4. [Advanced Scenarios](#advanced-scenarios)
11
- 5. [Integration Examples](#integration-examples)
12
-
13
- ---
14
-
15
- ## Basic Usage
16
-
17
- ### Hash a String
18
-
19
- ```typescript
20
- import { MD5Stream } from 'pure-md5';
21
-
22
- const stream = new MD5Stream();
23
- let digest = '';
24
-
25
- stream.on('md5', (result) => {
26
- digest = result.digest;
27
- });
28
-
29
- stream.end('Hello, World!');
30
- console.log(digest); // 65a8e27d8879283831b664bd8b7f0ad4
31
- ```
32
-
33
- ### Hash a Buffer
34
-
35
- ```typescript
36
- import { MD5Stream } from 'pure-md5';
37
-
38
- const data = Buffer.from('Hello, World!', 'utf8');
39
- const stream = new MD5Stream();
40
- let digest = '';
41
-
42
- stream.on('md5', (result) => {
43
- digest = result.digest;
44
- });
45
-
46
- stream.end(data);
47
- console.log(digest); // 65a8e27d8879283831b664bd8b7f0ad4
48
- ```
49
-
50
- ### Using fromStream (Promise-based)
51
-
52
- ```typescript
53
- import { fromStream } from 'pure-md5';
54
- import { Readable } from 'stream';
55
-
56
- const source = Readable.from(['Hello', ' ', 'World!']);
57
- const { result } = fromStream(source);
58
-
59
- result.then(({ digest, bytesProcessed }) => {
60
- console.log('MD5:', digest);
61
- console.log('Bytes:', bytesProcessed);
62
- });
63
- ```
64
-
65
- ### Using pipeThroughMD5
66
-
67
- ```typescript
68
- import { pipeThroughMD5 } from 'pure-md5';
69
- import { Readable } from 'stream';
70
-
71
- const source = Readable.from(['Hello', ' ', 'World!']);
72
- const { digest, bytesProcessed } = await pipeThroughMD5(source);
73
-
74
- console.log('MD5:', digest);
75
- console.log('Bytes:', bytesProcessed);
76
- ```
77
-
78
- ---
79
-
80
- ## File Operations
81
-
82
- ### Hash a File
83
-
84
- ```typescript
85
- import { hashFile } from 'pure-md5';
86
-
87
- const result = await hashFile('path/to/file.txt');
88
- console.log('MD5:', result.digest);
89
- console.log('Bytes:', result.bytesProcessed);
90
- ```
91
-
92
- ### Hash Multiple Files
93
-
94
- ```typescript
95
- import { hashFile } from 'pure-md5';
96
-
97
- async function hashFiles(files: string[]): Promise<Map<string, string>> {
98
- const results = new Map<string, string>();
99
-
100
- for (const file of files) {
101
- const result = await hashFile(file);
102
- results.set(file, result.digest);
103
- }
104
-
105
- return results;
106
- }
107
-
108
- const fileHashes = await hashFiles(['file1.txt', 'file2.txt', 'file3.txt']);
109
- fileHashes.forEach((hash, file) => console.log(`${file}: ${hash}`));
110
- ```
111
-
112
- ### Hash Files Concurrently
113
-
114
- ```typescript
115
- import { hashFile } from 'pure-md5';
116
-
117
- async function hashFilesConcurrently(files: string[], maxConcurrent = 4): Promise<Map<string, string>> {
118
- const results = new Map<string, string>();
119
- const queue = [...files];
120
-
121
- async function processNext() {
122
- if (queue.length === 0) return;
123
- const file = queue.shift();
124
- const result = await hashFile(file!);
125
- results.set(file!, result.digest);
126
- await processNext();
127
- }
128
-
129
- const workers = Array.from({ length: Math.min(maxConcurrent, files.length) }, processNext);
130
- await Promise.all(workers);
131
-
132
- return results;
133
- }
134
- ```
135
-
136
- ### Hash File with Progress
137
-
138
- ```typescript
139
- import { MD5Stream } from 'pure-md5';
140
- import fs from 'fs';
141
-
142
- async function hashFileWithProgress(filePath: string): Promise<string> {
143
- return new Promise((resolve, reject) => {
144
- const fileSize = fs.statSync(filePath).size;
145
- const stream = new MD5Stream();
146
- let processed = 0;
147
-
148
- stream.on('md5', (result) => {
149
- console.log('\nComplete!');
150
- console.log('MD5:', result.digest);
151
- resolve(result.digest);
152
- });
153
-
154
- stream.on('data', (chunk) => {
155
- processed += chunk.length;
156
- const progress = ((processed / fileSize) * 100).toFixed(1);
157
- process.stdout.write(`\rProgress: ${progress}%`);
158
- });
159
-
160
- fs.createReadStream(filePath).pipe(stream);
161
- });
162
- }
163
-
164
- await hashFileWithProgress('large-file.bin');
165
- ```
166
-
167
- ### Verify File Integrity
168
-
169
- ```typescript
170
- import { verifyFile } from 'pure-md5';
171
-
172
- async function verifyDownload(filePath: string, expectedHash: string): Promise<void> {
173
- const isVerified = await verifyFile(filePath, expectedHash);
174
-
175
- if (isVerified) {
176
- console.log('✓ File verified successfully!');
177
- } else {
178
- console.log('✗ File verification failed!');
179
- throw new Error('File integrity check failed');
180
- }
181
- }
182
-
183
- await verifyDownload('downloaded-file.zip', '5d41402abc4b2a76b9719d911017c592');
184
- ```
185
-
186
- ---
187
-
188
- ## Browser Usage
189
-
190
- ### Hash a File Upload
191
-
192
- ```typescript
193
- import { hashFile } from 'pure-md5';
194
-
195
- async function handleFileUpload(event: Event): Promise<void> {
196
- const input = event.target as HTMLInputElement;
197
- const file = input.files![0];
198
-
199
- const result = await hashFile(file);
200
- console.log('File MD5:', result.digest);
201
-
202
- // Upload with hash...
203
- }
204
-
205
- document.querySelector('input[type="file"]').addEventListener('change', handleFileUpload);
206
- ```
207
-
208
- ### Hash Blob from Canvas
209
-
210
- ```typescript
211
- import { hashBlob } from 'pure-md5';
212
-
213
- async function hashCanvas(canvas: HTMLCanvasElement): Promise<string> {
214
- return new Promise((resolve, reject) => {
215
- canvas.toBlob(async (blob) => {
216
- if (!blob) {
217
- reject(new Error('Failed to create blob'));
218
- return;
219
- }
220
-
221
- const result = await hashBlob(blob);
222
- resolve(result.digest);
223
- }, 'image/png');
224
- });
225
- }
226
-
227
- const digest = await hashCanvas(document.querySelector('canvas'));
228
- console.log('Canvas MD5:', digest);
229
- ```
230
-
231
- ### Stream File with Progress
232
-
233
- ```typescript
234
- import { MD5ReadableStream } from 'pure-md5';
235
-
236
- async function uploadWithHash(file: File, uploadUrl: string): Promise<void> {
237
- const fileStream = file.stream();
238
- const md5Stream = new MD5ReadableStream(fileStream);
239
-
240
- const reader = md5Stream.getReader();
241
- let bytesProcessed = 0;
242
-
243
- // Consume stream and track progress
244
- while (true) {
245
- const { done, value } = await reader.read();
246
- if (done) break;
247
-
248
- bytesProcessed += value.length;
249
- const progress = (bytesProcessed / file.size * 100).toFixed(1);
250
- console.log(`Upload progress: ${progress}%`);
251
- }
252
-
253
- const result = await md5Stream.getResult();
254
- console.log('Upload complete. MD5:', result.digest);
255
-
256
- // Now upload with hash metadata
257
- // await fetch(uploadUrl, { method: 'POST', body: file, headers: { 'X-MD5': result.digest } });
258
- }
259
- ```
260
-
261
- ---
262
-
263
- ## Advanced Scenarios
264
-
265
- ### Custom add32 Function
266
-
267
- ```typescript
268
- import { MD5Stream } from 'pure-md5';
269
-
270
- // For testing - use a known add32 implementation
271
- const customAdd32 = (x: number, y: number): number => {
272
- // Custom implementation for compatibility testing
273
- const result = x + y;
274
- return (result & 0xffffffff) >>> 0;
275
- };
276
-
277
- const stream = new MD5Stream({ add32: customAdd32 });
278
- let digest = '';
279
-
280
- stream.on('md5', (result) => {
281
- digest = result.digest;
282
- });
283
-
284
- stream.end('test with custom add32');
285
- console.log(digest);
286
- ```
287
-
288
- ### Stream with Timeout
289
-
290
- ```typescript
291
- import { MD5Stream } from 'pure-md5';
292
-
293
- async function hashWithTimeout(source: NodeJS.ReadableStream, timeoutMs: number): Promise<string> {
294
- return new Promise((resolve, reject) => {
295
- const timeout = setTimeout(() => {
296
- reject(new Error('Hashing timeout'));
297
- }, timeoutMs);
298
-
299
- const stream = new MD5Stream();
300
-
301
- stream.on('md5', (result) => {
302
- clearTimeout(timeout);
303
- resolve(result.digest);
304
- });
305
-
306
- stream.on('error', (error) => {
307
- clearTimeout(timeout);
308
- reject(error);
309
- });
310
-
311
- source.pipe(stream);
312
- });
313
- }
314
-
315
- try {
316
- const digest = await hashWithTimeout(fs.createReadStream('file.txt'), 5000);
317
- console.log('MD5:', digest);
318
- } catch (error) {
319
- console.error('Error:', error.message);
320
- }
321
- ```
322
-
323
- ### Multiple Hashes in Parallel
324
-
325
- ```typescript
326
- import { hashFile } from 'pure-md5';
327
-
328
- interface HashResult {
329
- file: string;
330
- digest: string;
331
- size: number;
332
- }
333
-
334
- async function hashFilesParallel(files: string[]): Promise<HashResult[]> {
335
- const promises = files.map(async (file) => {
336
- const result = await hashFile(file);
337
- const size = (await fs.promises.stat(file)).size;
338
- return { file, digest: result.digest, size };
339
- });
340
-
341
- return Promise.all(promises);
342
- }
343
-
344
- const results = await hashFilesParallel(['file1.txt', 'file2.txt', 'file3.txt']);
345
- results.forEach(r => console.log(`${r.file}: ${r.digest} (${r.size} bytes)`));
346
- ```
347
-
348
- ### Detect File Changes
349
-
350
- ```typescript
351
- import { hashFile } from 'pure-md5';
352
-
353
- interface FileHash {
354
- path: string;
355
- hash: string;
356
- timestamp: number;
357
- }
358
-
359
- async function detectChanges(previous: Map<string, FileHash>, currentFiles: string[]): Promise<void> {
360
- const changes: string[] = [];
361
-
362
- // Check existing files
363
- for (const file of currentFiles) {
364
- const currentHash = await hashFile(file);
365
- const previousHash = previous.get(file);
366
-
367
- if (!previousHash || previousHash.hash !== currentHash.digest) {
368
- changes.push(file);
369
- }
370
- }
371
-
372
- // Check for deleted files
373
- for (const [file] of previous) {
374
- if (!currentFiles.includes(file)) {
375
- changes.push(file);
376
- }
377
- }
378
-
379
- if (changes.length > 0) {
380
- console.log('Changed files:', changes);
381
- }
382
- }
383
- ```
384
-
385
- ---
386
-
387
- ## Integration Examples
388
-
389
- ### Express.js Middleware
390
-
391
- ```typescript
392
- import { hashFile } from 'pure-md5';
393
- import express, { Request, Response, NextFunction } from 'express';
394
-
395
- interface RequestWithHash extends Request {
396
- fileHash?: string;
397
- }
398
-
399
- const app = express();
400
-
401
- // Middleware to compute file hash
402
- app.use((req: RequestWithHash, res: Response, next: NextFunction) => {
403
- if (req.body && req.body.file) {
404
- hashFile(req.body.file.path)
405
- .then(result => {
406
- req.fileHash = result.digest;
407
- next();
408
- })
409
- .catch(next);
410
- } else {
411
- next();
412
- }
413
- });
414
-
415
- app.post('/upload', (req: RequestWithHash, res: Response) => {
416
- res.json({
417
- hash: req.fileHash,
418
- message: 'File uploaded'
419
- });
420
- });
421
- ```
422
-
423
- ### AWS Lambda Function
424
-
425
- ```typescript
426
- import { hashFile } from 'pure-md5';
427
- import { S3Client, GetObjectCommand } from '@aws-sdk/client-s3';
428
-
429
- const s3 = new S3Client({});
430
-
431
- export async function handler(event: any): Promise<any> {
432
- const bucket = event.bucket;
433
- const key = event.key;
434
-
435
- // Get object from S3
436
- const command = new GetObjectCommand({ Bucket: bucket, Key: key });
437
- const response = await s3.send(command);
438
-
439
- // Hash the content
440
- const content = await response.Body!.transformToString();
441
- const hash = await hashFile(content);
442
-
443
- return {
444
- statusCode: 200,
445
- body: JSON.stringify({
446
- md5: hash.digest,
447
- size: hash.bytesProcessed
448
- })
449
- };
450
- }
451
- ```
452
-
453
- ### GraphQL Resolver
454
-
455
- ```typescript
456
- import { hashFile } from 'pure-md5';
457
-
458
- const resolvers = {
459
- Query: {
460
- fileHash: async (_, { path }: { path: string }) => {
461
- const result = await hashFile(path);
462
- return {
463
- digest: result.digest,
464
- bytesProcessed: result.bytesProcessed,
465
- path
466
- };
467
- }
468
- }
469
- };
470
- ```
471
-
472
- ### CLI Tool
473
-
474
- ```typescript
475
- #!/usr/bin/env node
476
- import { hashFile } from 'pure-md5';
477
- import fs from 'fs';
478
-
479
- async function main() {
480
- const filePath = process.argv[2];
481
-
482
- if (!filePath) {
483
- console.error('Usage: md5-hash <file>');
484
- process.exit(1);
485
- }
486
-
487
- try {
488
- const result = await hashFile(filePath);
489
- console.log(result.digest);
490
- } catch (error) {
491
- console.error('Error:', error.message);
492
- process.exit(1);
493
- }
494
- }
495
-
496
- main();
497
- ```
498
-
499
- ### React Component
500
-
501
- ```typescript
502
- import { useState, useEffect } from 'react';
503
- import { hashFile } from 'pure-md5';
504
-
505
- function FileHasher() {
506
- const [file, setFile] = useState<File | null>(null);
507
- const [hash, setHash] = useState<string>('');
508
- const [loading, setLoading] = useState(false);
509
-
510
- const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
511
- if (event.target.files && event.target.files[0]) {
512
- setFile(event.target.files[0]);
513
- }
514
- };
515
-
516
- useEffect(() => {
517
- if (file) {
518
- setLoading(true);
519
- hashFile(file)
520
- .then(result => {
521
- setHash(result.digest);
522
- setLoading(false);
523
- })
524
- .catch(error => {
525
- console.error(error);
526
- setLoading(false);
527
- });
528
- }
529
- }, [file]);
530
-
531
- return (
532
- <div>
533
- <input type="file" onChange={handleFileChange} />
534
- {loading && <p>Computing hash...</p>}
535
- {hash && <p>MD5: {hash}</p>}
536
- </div>
537
- );
538
- }
539
- ```
540
-
541
- ### Node.js CLI Tool with Progress
542
-
543
- ```typescript
544
- #!/usr/bin/env node
545
- import { MD5Stream } from 'pure-md5';
546
- import fs from 'fs';
547
- import readline from 'readline';
548
-
549
- const rl = readline.createInterface({
550
- input: process.stdin,
551
- output: process.stdout
552
- });
553
-
554
- const filePath = process.argv[2];
555
-
556
- if (!filePath) {
557
- console.error('Usage: md5-hash <file>');
558
- process.exit(1);
559
- }
560
-
561
- const fileSize = fs.statSync(filePath).size;
562
- const stream = new MD5Stream();
563
- let processed = 0;
564
-
565
- const updateProgress = () => {
566
- const progress = ((processed / fileSize) * 100).toFixed(1);
567
- process.stdout.write(`\r${progress}% [${'#'.padEnd(50, ' ').substring(0, Math.floor(progress / 2))}]`);
568
- };
569
-
570
- stream.on('data', (chunk) => {
571
- processed += chunk.length;
572
- if (processed % (64 * 1024) === 0) { // Update every 64KB
573
- updateProgress();
574
- }
575
- });
576
-
577
- stream.on('md5', (result) => {
578
- updateProgress();
579
- console.log(`\n${result.digest} ${filePath}`);
580
- rl.close();
581
- });
582
-
583
- stream.on('error', (error) => {
584
- console.error(`Error: ${error.message}`);
585
- rl.close();
586
- process.exit(1);
587
- });
588
-
589
- fs.createReadStream(filePath).pipe(stream);
590
- ```
591
-
592
- ---
593
-
594
- ## Performance Examples
595
-
596
- ### Optimal File Hashing
597
-
598
- ```typescript
599
- import { MD5Stream } from 'pure-md5';
600
- import fs from 'fs';
601
-
602
- async function optimalHashFile(filePath: string): Promise<string> {
603
- return new Promise((resolve, reject) => {
604
- const stream = new MD5Stream();
605
-
606
- stream.on('md5', (result) => {
607
- resolve(result.digest);
608
- });
609
-
610
- stream.on('error', reject);
611
-
612
- // Use piping for optimal performance
613
- fs.createReadStream(filePath).pipe(stream);
614
- });
615
- }
616
- ```
617
-
618
- ### Memory-Efficient Large File Processing
619
-
620
- ```typescript
621
- import { MD5Stream } from 'pure-md5';
622
-
623
- async function hashLargeFileEfficiently(source: NodeJS.ReadableStream): Promise<string> {
624
- return new Promise((resolve, reject) => {
625
- const stream = new MD5Stream();
626
-
627
- stream.on('md5', (result) => {
628
- resolve(result.digest);
629
- });
630
-
631
- stream.on('error', reject);
632
-
633
- // Set optimal buffer size
634
- source.setEncoding('binary');
635
- source.pipe(stream);
636
- });
637
- }
638
- ```
639
-
640
- ### Batch Processing
641
-
642
- ```typescript
643
- import { hashFile } from 'pure-md5';
644
-
645
- async function batchHashFiles(
646
- files: string[],
647
- batchSize: number = 10
648
- ): Promise<Map<string, string>> {
649
- const results = new Map<string, string>();
650
-
651
- for (let i = 0; i < files.length; i += batchSize) {
652
- const batch = files.slice(i, i + batchSize);
653
- const batchResults = await Promise.all(batch.map(f => hashFile(f)));
654
-
655
- batch.forEach((file, index) => {
656
- results.set(file, batchResults[index].digest);
657
- });
658
- }
659
-
660
- return results;
661
- }
662
- ```
663
-
664
- ## See Also
665
-
666
- - [STREAM_API.md](STREAM_API.md) - Complete API documentation
667
- - [MIGRATION_GUIDE_STREAMS.md](MIGRATION_GUIDE_STREAMS.md) - Migration examples
668
- - [STREAM_TROUBLESHOOTING.md](STREAM_TROUBLESHOOTING.md) - Common issues
669
- - [STREAM_BENCHMARKS.md](STREAM_BENCHMARKS.md) - Performance benchmarks