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
@@ -1,355 +0,0 @@
1
- /**
2
- * WHATWG Streams tests for browser environments
3
- * These tests verify the WHATWG Streams implementation works correctly
4
- */
5
-
6
- import { MD5ReadableStream, hashBlob } from '../../src/stream/whatwg-stream.js';
7
- import { md5Core } from '../../src/core/index.js';
8
-
9
- // Skip tests if WHATWG Streams are not available
10
- const canRunWhatwgTests = typeof ReadableStream !== 'undefined' && typeof Blob !== 'undefined';
11
-
12
- if (!canRunWhatwgTests) {
13
- console.log('WHATWG Streams not available, skipping tests');
14
- // Create empty tests to satisfy Jest requirement
15
- describe('MD5ReadableStream', () => {
16
- it('should skip when WHATWG Streams not available', () => {
17
- console.log('Skipping: WHATWG Streams not available');
18
- });
19
- });
20
-
21
- describe('hashBlob', () => {
22
- it('should skip when WHATWG Streams not available', () => {
23
- console.log('Skipping: WHATWG Streams not available');
24
- });
25
- });
26
-
27
- describe('integration', () => {
28
- it('should skip when WHATWG Streams not available', () => {
29
- console.log('Skipping: WHATWG Streams not available');
30
- });
31
- });
32
- } else {
33
-
34
- // Mock FileReader for Node.js environment
35
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
36
- (global as any).FileReader = class {
37
- static readonly EMPTY = 0;
38
- static readonly LOADING = 1;
39
- static readonly DONE = 2;
40
-
41
- _result: ArrayBuffer | string | null = null;
42
- onload: ((event: any) => void) | null = null;
43
- onerror: ((event: any) => void) | null = null;
44
-
45
- readAsArrayBuffer(blob: Blob) {
46
- blob.arrayBuffer().then((buffer) => {
47
- this._result = buffer;
48
- this.onload?.({
49
- target: {
50
- result: buffer
51
- }
52
- });
53
- }).catch((error) => {
54
- this.onerror?.({ error });
55
- });
56
- }
57
- };
58
-
59
- describe('MD5ReadableStream', () => {
60
- test('should compute MD5 hash for empty stream', async () => {
61
- const source = new ReadableStream({
62
- start(controller) {
63
- controller.close();
64
- }
65
- });
66
-
67
- const result = await MD5ReadableStream.hash(source);
68
-
69
- expect(result.digest).toBe(md5Core(''));
70
- expect(result.bytesProcessed).toBe(0);
71
- }, 10000);
72
-
73
- test('should compute MD5 hash for simple string', async () => {
74
- const input = 'hello';
75
- const source = new ReadableStream({
76
- start(controller) {
77
- controller.enqueue(new TextEncoder().encode(input));
78
- controller.close();
79
- }
80
- });
81
-
82
- const result = await MD5ReadableStream.hash(source);
83
-
84
- expect(result.digest).toBe(md5Core(input));
85
- expect(result.bytesProcessed).toBe(input.length);
86
- }, 10000);
87
-
88
- test('should compute MD5 hash for longer string', async () => {
89
- const input = 'a'.repeat(1000);
90
- const source = new ReadableStream({
91
- start(controller) {
92
- controller.enqueue(new TextEncoder().encode(input));
93
- controller.close();
94
- }
95
- });
96
-
97
- const result = await MD5ReadableStream.hash(source);
98
-
99
- expect(result.digest).toBe(md5Core(input));
100
- expect(result.bytesProcessed).toBe(input.length);
101
- }, 10000);
102
-
103
- test('should process chunked data correctly', async () => {
104
- const input = 'hello world';
105
- const source = new ReadableStream({
106
- start(controller) {
107
- controller.enqueue(new TextEncoder().encode('hello '));
108
- controller.enqueue(new TextEncoder().encode('world'));
109
- controller.close();
110
- }
111
- });
112
-
113
- const result = await MD5ReadableStream.hash(source);
114
-
115
- expect(result.digest).toBe(md5Core(input));
116
- expect(result.bytesProcessed).toBe(input.length);
117
- }, 10000);
118
-
119
- test('should handle multiple chunks of varying sizes', async () => {
120
- const input = 'This is a test string with multiple chunks';
121
- const chunks = ['This ', 'is a', ' test', ' string', ' with', ' multi', 'ple c', 'hunks'];
122
-
123
- const source = new ReadableStream({
124
- start(controller) {
125
- chunks.forEach(chunk => controller.enqueue(new TextEncoder().encode(chunk)));
126
- controller.close();
127
- }
128
- });
129
-
130
- const result = await MD5ReadableStream.hash(source);
131
-
132
- expect(result.digest).toBe(md5Core(input));
133
- expect(result.bytesProcessed).toBe(input.length);
134
- }, 10000);
135
-
136
- test('should handle data that exactly fills 64-byte blocks', async () => {
137
- const input = 'a'.repeat(64);
138
- const source = new ReadableStream({
139
- start(controller) {
140
- controller.enqueue(new TextEncoder().encode(input));
141
- controller.close();
142
- }
143
- });
144
-
145
- const result = await MD5ReadableStream.hash(source);
146
-
147
- expect(result.digest).toBe(md5Core(input));
148
- expect(result.bytesProcessed).toBe(input.length);
149
- }, 10000);
150
-
151
- test('should handle data that is multiple of 64 bytes', async () => {
152
- const input = 'a'.repeat(128);
153
- const source = new ReadableStream({
154
- start(controller) {
155
- controller.enqueue(new TextEncoder().encode(input));
156
- controller.close();
157
- }
158
- });
159
-
160
- const result = await MD5ReadableStream.hash(source);
161
-
162
- expect(result.digest).toBe(md5Core(input));
163
- expect(result.bytesProcessed).toBe(input.length);
164
- }, 10000);
165
-
166
- test('should handle special characters', async () => {
167
- const input = '!@#$%^&*()_+-=[]{}|;:,.<>?';
168
- const source = new ReadableStream({
169
- start(controller) {
170
- controller.enqueue(new TextEncoder().encode(input));
171
- controller.close();
172
- }
173
- });
174
-
175
- const result = await MD5ReadableStream.hash(source);
176
-
177
- expect(result.digest).toBe(md5Core(input));
178
- expect(result.bytesProcessed).toBe(input.length);
179
- }, 10000);
180
-
181
- test('should emit bytesProcessed correctly', async () => {
182
- const totalBytes = 256;
183
- const chunkSize = 64;
184
-
185
- const source = new ReadableStream({
186
- start(controller) {
187
- const chunk = new TextEncoder().encode('a'.repeat(chunkSize));
188
- for (let i = 0; i < 4; i++) {
189
- controller.enqueue(chunk);
190
- }
191
- controller.close();
192
- }
193
- });
194
-
195
- const result = await MD5ReadableStream.hash(source);
196
-
197
- expect(result.bytesProcessed).toBe(totalBytes);
198
- expect(result.digest.length).toBe(32);
199
- }, 10000);
200
-
201
- test('should support custom add32 function', async () => {
202
- const input = 'custom add32 test';
203
- const source = new ReadableStream({
204
- start(controller) {
205
- controller.enqueue(new TextEncoder().encode(input));
206
- controller.close();
207
- }
208
- });
209
-
210
- const customAdd32 = (x: number, y: number) => (x + y) & 0xffffffff;
211
- const result = await MD5ReadableStream.hash(source, { add32: customAdd32 });
212
-
213
- expect(result.digest).toBe(md5Core(input));
214
- expect(result.bytesProcessed).toBe(input.length);
215
- }, 10000);
216
-
217
- test('should handle sequential processing', async () => {
218
- const parts = ['Hello, ', 'World!', ' This is ', 'MD5 streaming.'];
219
- const full = parts.join('');
220
-
221
- const source = new ReadableStream({
222
- start(controller) {
223
- parts.forEach(part => controller.enqueue(new TextEncoder().encode(part)));
224
- controller.close();
225
- }
226
- });
227
-
228
- const result = await MD5ReadableStream.hash(source);
229
-
230
- expect(result.digest).toBe(md5Core(full));
231
- expect(result.bytesProcessed).toBe(full.length);
232
- }, 10000);
233
-
234
- test('should handle single byte chunks', async () => {
235
- const input = 'a';
236
- const source = new ReadableStream({
237
- start(controller) {
238
- controller.enqueue(new TextEncoder().encode(input));
239
- controller.close();
240
- }
241
- });
242
-
243
- const result = await MD5ReadableStream.hash(source);
244
-
245
- expect(result.digest).toBe(md5Core(input));
246
- expect(result.bytesProcessed).toBe(input.length);
247
- }, 10000);
248
-
249
- test('should emit valid hex digest', async () => {
250
- const source = new ReadableStream({
251
- start(controller) {
252
- controller.enqueue(new TextEncoder().encode('test'));
253
- controller.close();
254
- }
255
- });
256
-
257
- const result = await MD5ReadableStream.hash(source);
258
-
259
- // MD5 digest should be 32 hex characters
260
- expect(result.digest).toMatch(/^[0-9a-f]{32}$/);
261
- expect(result.digest.length).toBe(32);
262
- }, 10000);
263
-
264
- test('should get current state during processing', async () => {
265
- const source = new ReadableStream({
266
- start(controller) {
267
- controller.enqueue(new TextEncoder().encode('test'));
268
- controller.close();
269
- }
270
- });
271
-
272
- const stream = new MD5ReadableStream(source);
273
-
274
- // Check initial state before reading
275
- const initialState = stream.getCurrentState();
276
- expect(initialState.state).toHaveLength(4);
277
- expect(initialState.bytesProcessed).toBe(0);
278
-
279
- // Read some data
280
- const reader = stream.getReader();
281
- await reader.read();
282
-
283
- // Check state after reading
284
- const afterDataState = stream.getCurrentState();
285
- expect(afterDataState.bytesProcessed).toBe(4);
286
-
287
- // Check bytes processed getter
288
- expect(stream.getBytesProcessed()).toBe(4);
289
- }, 10000);
290
-
291
- test('should handle empty chunks', async () => {
292
- const input = 'test';
293
- const source = new ReadableStream({
294
- start(controller) {
295
- controller.enqueue(new TextEncoder().encode(''));
296
- controller.enqueue(new TextEncoder().encode(input));
297
- controller.close();
298
- }
299
- });
300
-
301
- const result = await MD5ReadableStream.hash(source);
302
-
303
- expect(result.digest).toBe(md5Core(input));
304
- expect(result.bytesProcessed).toBe(input.length);
305
- }, 10000);
306
- });
307
-
308
- if (typeof Blob !== 'undefined') {
309
- describe('hashBlob', () => {
310
- test('should hash a Blob', async () => {
311
- const input = 'blob hash test';
312
- const blob = new Blob([input]);
313
-
314
- const result = await hashBlob(blob);
315
-
316
- expect(result.digest).toBe(md5Core(input));
317
- expect(result.bytesProcessed).toBe(input.length);
318
- }, 10000);
319
-
320
- test('should hash an empty Blob', async () => {
321
- const blob = new Blob([]);
322
-
323
- const result = await hashBlob(blob);
324
-
325
- expect(result.digest).toBe(md5Core(''));
326
- expect(result.bytesProcessed).toBe(0);
327
- }, 10000);
328
- });
329
- }
330
-
331
- describe('integration', () => {
332
- test('should handle large data correctly', async () => {
333
- const chunkSize = 1024 * 1024; // 1MB
334
- const numChunks = 3;
335
- const totalBytes = chunkSize * numChunks;
336
-
337
- const source = new ReadableStream({
338
- start(controller) {
339
- const chunk = new TextEncoder().encode('a'.repeat(chunkSize));
340
- for (let i = 0; i < numChunks; i++) {
341
- controller.enqueue(chunk);
342
- }
343
- controller.close();
344
- }
345
- });
346
-
347
- const result = await MD5ReadableStream.hash(source);
348
-
349
- // We're just testing that it processes the data without crashing
350
- // The actual hash doesn't matter for this test
351
- expect(result.bytesProcessed).toBe(totalBytes);
352
- expect(result.digest.length).toBe(32); // MD5 is 32 hex chars
353
- }, 10000);
354
- });
355
- }
@@ -1,335 +0,0 @@
1
- /**
2
- * WHATWG Streams tests for browser environments
3
- * These tests verify the WHATWG Streams implementation works correctly
4
- */
5
-
6
- import { MD5ReadableStream, hashReadableStream, createMD5ReadableStream, hashFile, hashBlob } from '../../src/stream/whatwg-stream.js';
7
- import { md5Core } from '../../src/core/index.js';
8
-
9
- describe('MD5ReadableStream', () => {
10
- test('should compute MD5 hash for empty stream', async () => {
11
- const source = new ReadableStream({
12
- start(controller) {
13
- controller.close();
14
- }
15
- });
16
-
17
- const result = await MD5ReadableStream.hash(source);
18
-
19
- expect(result.digest).toBe(md5Core(''));
20
- expect(result.bytesProcessed).toBe(0);
21
- });
22
-
23
- test('should compute MD5 hash for simple string', async () => {
24
- const input = 'hello';
25
- const source = new ReadableStream({
26
- start(controller) {
27
- controller.enqueue(new TextEncoder().encode(input));
28
- controller.close();
29
- }
30
- });
31
-
32
- const result = await MD5ReadableStream.hash(source);
33
-
34
- expect(result.digest).toBe(md5Core(input));
35
- expect(result.bytesProcessed).toBe(input.length);
36
- });
37
-
38
- test('should compute MD5 hash for longer string', async () => {
39
- const input = 'a'.repeat(1000);
40
- const source = new ReadableStream({
41
- start(controller) {
42
- controller.enqueue(new TextEncoder().encode(input));
43
- controller.close();
44
- }
45
- });
46
-
47
- const result = await MD5ReadableStream.hash(source);
48
-
49
- expect(result.digest).toBe(md5Core(input));
50
- expect(result.bytesProcessed).toBe(input.length);
51
- });
52
-
53
- test('should process chunked data correctly', async () => {
54
- const input = 'hello world';
55
- const source = new ReadableStream({
56
- start(controller) {
57
- controller.enqueue(new TextEncoder().encode('hello '));
58
- controller.enqueue(new TextEncoder().encode('world'));
59
- controller.close();
60
- }
61
- });
62
-
63
- const result = await MD5ReadableStream.hash(source);
64
-
65
- expect(result.digest).toBe(md5Core(input));
66
- expect(result.bytesProcessed).toBe(input.length);
67
- });
68
-
69
- test('should handle multiple chunks of varying sizes', async () => {
70
- const input = 'This is a test string with multiple chunks';
71
- const chunks = ['This ', 'is a', ' test', ' string', ' with', ' multi', 'ple c', 'hunks'];
72
-
73
- const source = new ReadableStream({
74
- start(controller) {
75
- chunks.forEach(chunk => controller.enqueue(new TextEncoder().encode(chunk)));
76
- controller.close();
77
- }
78
- });
79
-
80
- const result = await MD5ReadableStream.hash(source);
81
-
82
- expect(result.digest).toBe(md5Core(input));
83
- expect(result.bytesProcessed).toBe(input.length);
84
- });
85
-
86
- test('should handle data that exactly fills 64-byte blocks', async () => {
87
- const input = 'a'.repeat(64);
88
- const source = new ReadableStream({
89
- start(controller) {
90
- controller.enqueue(new TextEncoder().encode(input));
91
- controller.close();
92
- }
93
- });
94
-
95
- const result = await MD5ReadableStream.hash(source);
96
-
97
- expect(result.digest).toBe(md5Core(input));
98
- expect(result.bytesProcessed).toBe(input.length);
99
- });
100
-
101
- test('should handle data that is multiple of 64 bytes', async () => {
102
- const input = 'a'.repeat(128);
103
- const source = new ReadableStream({
104
- start(controller) {
105
- controller.enqueue(new TextEncoder().encode(input));
106
- controller.close();
107
- }
108
- });
109
-
110
- const result = await MD5ReadableStream.hash(source);
111
-
112
- expect(result.digest).toBe(md5Core(input));
113
- expect(result.bytesProcessed).toBe(input.length);
114
- });
115
-
116
- test('should handle special characters', async () => {
117
- const input = '!@#$%^&*()_+-=[]{}|;:,.<>?';
118
- const source = new ReadableStream({
119
- start(controller) {
120
- controller.enqueue(new TextEncoder().encode(input));
121
- controller.close();
122
- }
123
- });
124
-
125
- const result = await MD5ReadableStream.hash(source);
126
-
127
- expect(result.digest).toBe(md5Core(input));
128
- expect(result.bytesProcessed).toBe(input.length);
129
- });
130
-
131
- test('should emit bytesProcessed correctly', async () => {
132
- const totalBytes = 256;
133
- const chunkSize = 64;
134
-
135
- const source = new ReadableStream({
136
- start(controller) {
137
- const chunk = new TextEncoder().encode('a'.repeat(chunkSize));
138
- for (let i = 0; i < 4; i++) {
139
- controller.enqueue(chunk);
140
- }
141
- controller.close();
142
- }
143
- });
144
-
145
- const result = await MD5ReadableStream.hash(source);
146
-
147
- expect(result.bytesProcessed).toBe(totalBytes);
148
- expect(result.digest.length).toBe(32);
149
- });
150
-
151
- test('should support factory function createMD5ReadableStream', async () => {
152
- const input = 'factory test';
153
- const source = new ReadableStream({
154
- start(controller) {
155
- controller.enqueue(new TextEncoder().encode(input));
156
- controller.close();
157
- }
158
- });
159
-
160
- const stream = createMD5ReadableStream(source);
161
- const result = await stream.getResult();
162
-
163
- expect(result.digest).toBe(md5Core(input));
164
- expect(result.bytesProcessed).toBe(input.length);
165
- });
166
-
167
- test('should support custom add32 function', async () => {
168
- const input = 'custom add32 test';
169
- const source = new ReadableStream({
170
- start(controller) {
171
- controller.enqueue(new TextEncoder().encode(input));
172
- controller.close();
173
- }
174
- });
175
-
176
- const customAdd32 = (x: number, y: number) => (x + y) & 0xffffffff;
177
- const result = await MD5ReadableStream.hash(source, { add32: customAdd32 });
178
-
179
- expect(result.digest).toBe(md5Core(input));
180
- expect(result.bytesProcessed).toBe(input.length);
181
- });
182
-
183
- test('should handle sequential processing', async () => {
184
- const parts = ['Hello, ', 'World!', ' This is ', 'MD5 streaming.'];
185
- const full = parts.join('');
186
-
187
- const source = new ReadableStream({
188
- start(controller) {
189
- parts.forEach(part => controller.enqueue(new TextEncoder().encode(part)));
190
- controller.close();
191
- }
192
- });
193
-
194
- const result = await MD5ReadableStream.hash(source);
195
-
196
- expect(result.digest).toBe(md5Core(full));
197
- expect(result.bytesProcessed).toBe(full.length);
198
- });
199
-
200
- test('should handle single byte chunks', async () => {
201
- const input = 'a';
202
- const source = new ReadableStream({
203
- start(controller) {
204
- controller.enqueue(new TextEncoder().encode(input));
205
- controller.close();
206
- }
207
- });
208
-
209
- const result = await MD5ReadableStream.hash(source);
210
-
211
- expect(result.digest).toBe(md5Core(input));
212
- expect(result.bytesProcessed).toBe(input.length);
213
- });
214
-
215
- test('should emit valid hex digest', async () => {
216
- const source = new ReadableStream({
217
- start(controller) {
218
- controller.enqueue(new TextEncoder().encode('test'));
219
- controller.close();
220
- }
221
- });
222
-
223
- const result = await MD5ReadableStream.hash(source);
224
-
225
- // MD5 digest should be 32 hex characters
226
- expect(result.digest).toMatch(/^[0-9a-f]{32}$/);
227
- expect(result.digest.length).toBe(32);
228
- });
229
-
230
- test('should get current state during processing', async () => {
231
- const source = new ReadableStream({
232
- start(controller) {
233
- controller.enqueue(new TextEncoder().encode('test'));
234
- controller.close();
235
- }
236
- });
237
-
238
- const stream = new MD5ReadableStream(source);
239
-
240
- // Check initial state before reading
241
- const initialState = stream.getCurrentState();
242
- expect(initialState.state).toHaveLength(4);
243
- expect(initialState.bytesProcessed).toBe(0);
244
-
245
- // Read some data
246
- const reader = stream.getReader();
247
- await reader.read();
248
-
249
- // Check state after reading
250
- const afterDataState = stream.getCurrentState();
251
- expect(afterDataState.bytesProcessed).toBe(4);
252
-
253
- // Check bytes processed getter
254
- expect(stream.getBytesProcessed()).toBe(4);
255
- });
256
-
257
- test('should handle empty chunks', async () => {
258
- const input = 'test';
259
- const source = new ReadableStream({
260
- start(controller) {
261
- controller.enqueue(new TextEncoder().encode(''));
262
- controller.enqueue(new TextEncoder().encode(input));
263
- controller.close();
264
- }
265
- });
266
-
267
- const result = await MD5ReadableStream.hash(source);
268
-
269
- expect(result.digest).toBe(md5Core(input));
270
- expect(result.bytesProcessed).toBe(input.length);
271
- });
272
- });
273
-
274
- describe('hashReadableStream', () => {
275
- test('should hash a ReadableStream', async () => {
276
- const input = 'hash readable stream test';
277
- const source = new ReadableStream({
278
- start(controller) {
279
- controller.enqueue(new TextEncoder().encode(input));
280
- controller.close();
281
- }
282
- });
283
-
284
- const result = await hashReadableStream(source);
285
-
286
- expect(result.digest).toBe(md5Core(input));
287
- expect(result.bytesProcessed).toBe(input.length);
288
- });
289
- });
290
-
291
- describe('hashBlob', () => {
292
- test('should hash a Blob', async () => {
293
- const input = 'blob hash test';
294
- const blob = new Blob([input]);
295
-
296
- const result = await hashBlob(blob);
297
-
298
- expect(result.digest).toBe(md5Core(input));
299
- expect(result.bytesProcessed).toBe(input.length);
300
- });
301
-
302
- test('should hash an empty Blob', async () => {
303
- const blob = new Blob([]);
304
-
305
- const result = await hashBlob(blob);
306
-
307
- expect(result.digest).toBe(md5Core(''));
308
- expect(result.bytesProcessed).toBe(0);
309
- });
310
- });
311
-
312
- describe('integration', () => {
313
- test('should handle large data correctly', async () => {
314
- const chunkSize = 1024 * 1024; // 1MB
315
- const numChunks = 3;
316
- const totalBytes = chunkSize * numChunks;
317
-
318
- const source = new ReadableStream({
319
- start(controller) {
320
- const chunk = new TextEncoder().encode('a'.repeat(chunkSize));
321
- for (let i = 0; i < numChunks; i++) {
322
- controller.enqueue(chunk);
323
- }
324
- controller.close();
325
- }
326
- });
327
-
328
- const result = await MD5ReadableStream.hash(source);
329
-
330
- // We're just testing that it processes the data without crashing
331
- // The actual hash doesn't matter for this test
332
- expect(result.bytesProcessed).toBe(totalBytes);
333
- expect(result.digest.length).toBe(32); // MD5 is 32 hex chars
334
- });
335
- });