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.
- package/README.md +38 -24
- package/dist/adapters/ie11.cjs +1 -2
- package/dist/adapters/ie11.js +1 -2
- package/dist/adapters/node.cjs +1 -2
- package/dist/adapters/node.js +1 -2
- package/dist/adapters/webcrypto.cjs +1 -2
- package/dist/adapters/webcrypto.js +1 -2
- package/dist/index.cjs +1 -2
- package/dist/index.d.ts +149 -5
- package/dist/index.js +3 -2
- package/dist/md5.cjs +1 -0
- package/dist/md5.d.ts +20 -0
- package/dist/md5.js +1 -0
- package/dist/stream/md5-stream.cjs +1 -2
- package/dist/stream/md5-stream.js +1 -2
- package/dist/stream/whatwg-stream.cjs +1 -2
- package/dist/stream/whatwg-stream.js +1 -2
- package/dist/utils/detect.cjs +1 -2
- package/dist/utils/detect.js +3 -2
- package/package.json +10 -15
- package/pure-md5-0.2.1.tgz +0 -0
- package/test-tree-shake.mjs +12 -0
- package/.aliases +0 -19
- package/.bash_profile +0 -12
- package/.bash_prompt +0 -56
- package/.changeset/README.md +0 -32
- package/.changeset/config.json +0 -16
- package/.continue/mcpServers/new-mcp-server.yaml +0 -10
- package/.continue/rules +0 -29
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -35
- package/.github/ISSUE_TEMPLATE/documentation.md +0 -20
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
- package/.github/PULL_REQUEST_TEMPLATE.md +0 -35
- package/.github/workflows/npm-publish.yml +0 -33
- package/.github/workflows/release.yml +0 -42
- package/CHANGELOG.md +0 -9
- package/CONTRIBUTING.md +0 -203
- package/MIGRATION_GUIDE_STREAMS.md +0 -374
- package/STREAM_API.md +0 -582
- package/STREAM_BENCHMARKS.md +0 -232
- package/STREAM_EXAMPLES.md +0 -669
- package/STREAM_OPTIMIZATION_REPORT.md +0 -136
- package/STREAM_TROUBLESHOOTING.md +0 -537
- package/WEB_CRYPTO_TESTS_SUMMARY.md +0 -140
- package/WHATWG_STREAMS.md +0 -191
- package/__tests__/adapters/node-crypto.test.ts +0 -167
- package/__tests__/adapters/web-crypto-node.test.ts +0 -73
- package/__tests__/adapters/web-crypto.test.ts +0 -195
- package/__tests__/add32.test.ts +0 -33
- package/__tests__/fallback.test.ts +0 -345
- package/__tests__/hex.test.ts +0 -38
- package/__tests__/hex_chr.test.ts +0 -20
- package/__tests__/index.test.ts +0 -87
- package/__tests__/integration/fixtures/test-file.txt +0 -1
- package/__tests__/integration/md5-stream-file.test.ts +0 -293
- package/__tests__/integration/node-crypto-file.test.ts +0 -86
- package/__tests__/integration/web-crypto.test.ts +0 -38
- package/__tests__/md51.test.ts +0 -73
- package/__tests__/md5block.test.ts +0 -61
- package/__tests__/md5cycle.test.ts +0 -48
- package/__tests__/round-functions.test.ts +0 -87
- package/__tests__/stream/fs-utils.test.ts +0 -209
- package/__tests__/stream/md5-stream-edge-cases.test.ts +0 -461
- package/__tests__/stream/md5-stream.test.ts +0 -418
- package/__tests__/stream/whatwg-stream.test.ts +0 -355
- package/__tests__/stream/whatwg-stream.test.ts.bak2 +0 -335
- package/benchmarks/md5-stream.bench.ts +0 -212
- package/benchmarks/whatwg-stream.bench.ts +0 -180
- package/dist/adapters/ie11.cjs.map +0 -1
- package/dist/adapters/ie11.js.map +0 -1
- package/dist/adapters/node.cjs.map +0 -1
- package/dist/adapters/node.js.map +0 -1
- package/dist/adapters/webcrypto.cjs.map +0 -1
- package/dist/adapters/webcrypto.js.map +0 -1
- package/dist/chunk-2YXXFGBV.js +0 -2
- package/dist/chunk-2YXXFGBV.js.map +0 -1
- package/dist/chunk-4KSCMS4Q.js +0 -2
- package/dist/chunk-4KSCMS4Q.js.map +0 -1
- package/dist/chunk-6P2QV5SR.js +0 -4
- package/dist/chunk-6P2QV5SR.js.map +0 -1
- package/dist/chunk-G5WHEAIQ.js +0 -2
- package/dist/chunk-G5WHEAIQ.js.map +0 -1
- package/dist/chunk-H2K353LR.js +0 -2
- package/dist/chunk-H2K353LR.js.map +0 -1
- package/dist/chunk-JKVD5LHZ.js +0 -2
- package/dist/chunk-JKVD5LHZ.js.map +0 -1
- package/dist/chunk-NWQ4N5RX.js +0 -2
- package/dist/chunk-NWQ4N5RX.js.map +0 -1
- package/dist/chunk-PHZ7FTYF.js +0 -2
- package/dist/chunk-PHZ7FTYF.js.map +0 -1
- package/dist/chunk-PNZTVQA7.js +0 -2
- package/dist/chunk-PNZTVQA7.js.map +0 -1
- package/dist/chunk-R4JB5MBR.js +0 -2
- package/dist/chunk-R4JB5MBR.js.map +0 -1
- package/dist/chunk-VFOAY6XI.js +0 -2
- package/dist/chunk-VFOAY6XI.js.map +0 -1
- package/dist/chunk-XB5BQIEX.js +0 -2
- package/dist/chunk-XB5BQIEX.js.map +0 -1
- package/dist/core/index.cjs +0 -2
- package/dist/core/index.cjs.map +0 -1
- package/dist/core/index.d.cts +0 -19
- package/dist/core/index.d.ts +0 -19
- package/dist/core/index.js +0 -2
- package/dist/core/index.js.map +0 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -84
- package/dist/index.js.map +0 -1
- package/dist/stream/adapter.cjs +0 -2
- package/dist/stream/adapter.cjs.map +0 -1
- package/dist/stream/adapter.d.cts +0 -63
- package/dist/stream/adapter.d.ts +0 -63
- package/dist/stream/adapter.js +0 -2
- package/dist/stream/adapter.js.map +0 -1
- package/dist/stream/fs-utils.cjs +0 -2
- package/dist/stream/fs-utils.cjs.map +0 -1
- package/dist/stream/fs-utils.d.cts +0 -137
- package/dist/stream/fs-utils.d.ts +0 -137
- package/dist/stream/fs-utils.js +0 -2
- package/dist/stream/fs-utils.js.map +0 -1
- package/dist/stream/index.cjs +0 -2
- package/dist/stream/index.cjs.map +0 -1
- package/dist/stream/index.d.cts +0 -4
- package/dist/stream/index.d.ts +0 -4
- package/dist/stream/index.js +0 -2
- package/dist/stream/index.js.map +0 -1
- package/dist/stream/light/index.cjs +0 -2
- package/dist/stream/light/index.cjs.map +0 -1
- package/dist/stream/light/index.d.cts +0 -4
- package/dist/stream/light/index.d.ts +0 -4
- package/dist/stream/light/index.js +0 -2
- package/dist/stream/light/index.js.map +0 -1
- package/dist/stream/md5-stream.cjs.map +0 -1
- package/dist/stream/md5-stream.js.map +0 -1
- package/dist/stream/whatwg-stream.cjs.map +0 -1
- package/dist/stream/whatwg-stream.js.map +0 -1
- package/dist/types-edGoGJ5V.d.cts +0 -42
- package/dist/types-edGoGJ5V.d.ts +0 -42
- package/dist/utils/detect.cjs.map +0 -1
- package/dist/utils/detect.js.map +0 -1
- package/planning/03-optimization-size-tree-shaking/01-es-modules-tree-shaking.md +0 -152
- package/planning/03-optimization-size-tree-shaking/02-consolidate-modules.md +0 -65
- package/planning/03-optimization-size-tree-shaking/03-remove-duplicate-add32.md +0 -93
- package/planning/03-optimization-size-tree-shaking/04-remove-runtime-check.md +0 -102
- package/planning/03-optimization-size-tree-shaking/05-optimize-loops-performance.md +0 -107
- package/planning/03-optimization-size-tree-shaking/06-tsup-formats-configuration.md +0 -227
- package/planning/03-optimization-size-tree-shaking/07-multiple-build-formats.md +0 -228
- package/planning/03-optimization-size-tree-shaking/08-benchmarks-metrics.md +0 -34
- package/planning/03-optimization-size-tree-shaking/MIGRATION_GUIDE.md +0 -260
- package/planning/03-optimization-size-tree-shaking/README.md +0 -173
- package/planning/03-optimization-size-tree-shaking/SUMMARY.md +0 -168
- package/planning/04-adapter-backend/03-backend-web-crypto.md +0 -149
- package/planning/04-adapter-backend/04-backend-node-crypto.md +0 -181
- package/planning/04-adapter-backend/05-backend-pure-js.md +0 -174
- package/planning/04-adapter-backend/06-backend-ie11.md +0 -158
- package/planning/04-adapter-backend/07-detection-environment.md +0 -232
- package/planning/04-adapter-backend/08-detection-backend.md +0 -210
- package/planning/04-adapter-backend/09-adapter-unified.md +0 -255
- package/planning/04-adapter-backend/10-fallback-mechanism.md +0 -333
- package/planning/04-adapter-backend/11-tests-backend-web-crypto.md +0 -191
- package/planning/04-adapter-backend/12-tests-backend-node-crypto.md +0 -222
- package/planning/04-adapter-backend/README.md +0 -45
- package/planning/05-documentation-publishing/01-README-optimization.md +0 -105
- package/planning/05-documentation-publishing/02-VitePress-site-evaluation.md +0 -136
- package/planning/05-documentation-publishing/03-Changeset-setup.md +0 -192
- package/planning/05-documentation-publishing/04-GitHub-templates.md +0 -252
- package/planning/05-documentation-publishing/README.md +0 -22
- package/planning/05-documentation-publishing/STATUS.md +0 -222
- package/planning/prd.md +0 -405
- package/planning/streams/01-create-md5stream-class.md +0 -69
- package/planning/streams/02-create-factory-api.md +0 -65
- package/planning/streams/03-fs-integration.md +0 -37
- package/planning/streams/04-whatwg-streams-support.md +0 -37
- package/planning/streams/05-audit-optimization.md +0 -121
- package/planning/streams/06-comprehensive-tests-docs.md +0 -137
- package/planning/streams/07-architecture-integration.md +0 -38
- package/planning/streams/README.md +0 -98
- package/tsup.config.ts +0 -24
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
# Web Crypto Backend Tests - Implementation Summary
|
|
2
|
-
|
|
3
|
-
## Overview
|
|
4
|
-
Successfully implemented comprehensive tests for Web Crypto Backend as specified in task 11.
|
|
5
|
-
|
|
6
|
-
## Test Files Created
|
|
7
|
-
|
|
8
|
-
### 1. `__tests__/adapters/web-crypto.test.ts`
|
|
9
|
-
Comprehensive test suite for WebCryptoBackend with the following test categories:
|
|
10
|
-
|
|
11
|
-
#### Basic Hashing (5 tests)
|
|
12
|
-
- ✅ Hash string correctly ('hello')
|
|
13
|
-
- ✅ Hash empty string
|
|
14
|
-
- ✅ Hash special characters ('!@#$%^&*()')
|
|
15
|
-
- ✅ Hash unicode characters ('Привет мир')
|
|
16
|
-
- ✅ Hash long string (10,000 characters)
|
|
17
|
-
|
|
18
|
-
#### Binary Data (3 tests)
|
|
19
|
-
- ✅ Hash Uint8Array
|
|
20
|
-
- ✅ Hash ArrayBuffer
|
|
21
|
-
- ✅ Hash empty Uint8Array
|
|
22
|
-
|
|
23
|
-
#### Availability (1 test)
|
|
24
|
-
- ✅ Check Web Crypto API availability
|
|
25
|
-
|
|
26
|
-
#### Performance (1 test)
|
|
27
|
-
- ✅ Hash 1MB data efficiently (should complete in <1 second)
|
|
28
|
-
|
|
29
|
-
#### Consistency (2 tests)
|
|
30
|
-
- ✅ Same hash for same input
|
|
31
|
-
- ✅ Different hash for different inputs
|
|
32
|
-
|
|
33
|
-
#### Interface Compliance (4 tests)
|
|
34
|
-
- ✅ Correct name and version
|
|
35
|
-
- ✅ Reset method exists
|
|
36
|
-
- ✅ Update throws error (no streaming support)
|
|
37
|
-
- ✅ Digest throws error (no streaming support)
|
|
38
|
-
|
|
39
|
-
**Total: 16 tests - All Passing**
|
|
40
|
-
|
|
41
|
-
### 2. `__tests__/adapters/web-crypto-node.test.ts`
|
|
42
|
-
Node.js-specific tests for Web Crypto Backend
|
|
43
|
-
|
|
44
|
-
#### Tests (4 tests)
|
|
45
|
-
- ✅ WebCrypto available in Node.js 15+
|
|
46
|
-
- ✅ Hash string correctly
|
|
47
|
-
- ✅ Hash empty string
|
|
48
|
-
- ✅ Work with binary data
|
|
49
|
-
|
|
50
|
-
**Conditions:**
|
|
51
|
-
- Only runs in Node.js environment
|
|
52
|
-
- Only runs in Node.js 15+ (or 14.17+ with flag)
|
|
53
|
-
|
|
54
|
-
**Total: 4 tests - All Passing**
|
|
55
|
-
|
|
56
|
-
### 3. `__tests__/integration/web-crypto.test.ts`
|
|
57
|
-
Integration tests for Web Crypto Backend
|
|
58
|
-
|
|
59
|
-
#### Tests (5 tests)
|
|
60
|
-
- ✅ md5 function with default backend
|
|
61
|
-
- ✅ Handle empty string
|
|
62
|
-
- ✅ Handle unicode
|
|
63
|
-
- ✅ Detect available backends
|
|
64
|
-
- ✅ md5Adapter with webcrypto
|
|
65
|
-
|
|
66
|
-
**Total: 5 tests - All Passing**
|
|
67
|
-
|
|
68
|
-
## Test Coverage
|
|
69
|
-
|
|
70
|
-
### Code Coverage Results
|
|
71
|
-
- **WebCrypto Backend**: 100% statement coverage
|
|
72
|
-
- **WebCrypto Backend**: 100% branch coverage
|
|
73
|
-
- **Overall Project**: 79.79% statement coverage
|
|
74
|
-
|
|
75
|
-
### Coverage Details
|
|
76
|
-
```
|
|
77
|
-
src/adapters/webcrypto.ts | 100 | 100 | 85.71 | 100 |
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
## Implementation Notes
|
|
81
|
-
|
|
82
|
-
### Web Crypto Backend Implementation
|
|
83
|
-
The WebCryptoBackend in `src/adapters/webcrypto.ts` was updated to:
|
|
84
|
-
|
|
85
|
-
1. **Check Web Crypto API availability** - Returns `true` if `crypto.subtle.digest` is available
|
|
86
|
-
2. **Fallback to Pure JS implementation** - Since Web Crypto API doesn't support MD5 in most browsers, the backend falls back to the existing pure JS implementation
|
|
87
|
-
3. **Maintain interface compliance** - Implements all required methods from MD5Backend interface
|
|
88
|
-
4. **Proper error handling** - Throws descriptive errors for unsupported streaming operations
|
|
89
|
-
|
|
90
|
-
### Key Design Decisions
|
|
91
|
-
|
|
92
|
-
1. **Fallback Strategy**: Since Web Crypto API doesn't support MD5 natively, the backend falls back to pure JS implementation while still providing the Web Crypto environment detection.
|
|
93
|
-
|
|
94
|
-
2. **Performance**: The performance test verifies that even with the fallback, 1MB data can be hashed efficiently (<1 second).
|
|
95
|
-
|
|
96
|
-
3. **Unicode Support**: The implementation uses the same encoding (UTF-16) as the original pure-md5 library for consistency.
|
|
97
|
-
|
|
98
|
-
## Test Execution Results
|
|
99
|
-
|
|
100
|
-
All 97 tests pass successfully:
|
|
101
|
-
- 12 test suites
|
|
102
|
-
- 97 individual tests
|
|
103
|
-
- 0 failures
|
|
104
|
-
|
|
105
|
-
### Test Output
|
|
106
|
-
```
|
|
107
|
-
Test Suites: 12 passed, 12 total
|
|
108
|
-
Tests: 97 passed, 97 total
|
|
109
|
-
Snapshots: 0 total
|
|
110
|
-
Time: 9.728 s
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
## Files Modified
|
|
114
|
-
|
|
115
|
-
1. **`src/adapters/webcrypto.ts`**
|
|
116
|
-
- Updated to use pure JS fallback for MD5
|
|
117
|
-
- Maintains Web Crypto API detection
|
|
118
|
-
|
|
119
|
-
2. **`src/index.ts`**
|
|
120
|
-
- Added PureJSBackend export
|
|
121
|
-
- Added BackendDetector, detector, FallbackManager, fallbackManager, robustHash, MetricsCollector, metrics exports
|
|
122
|
-
|
|
123
|
-
3. **`src/utils/detect.ts`**
|
|
124
|
-
- Already had comprehensive backend detection utilities
|
|
125
|
-
|
|
126
|
-
## Files Added
|
|
127
|
-
|
|
128
|
-
1. `__tests__/adapters/web-crypto.test.ts` - Main Web Crypto backend tests
|
|
129
|
-
2. `__tests__/adapters/web-crypto-node.test.ts` - Node.js specific tests
|
|
130
|
-
3. `__tests__/integration/web-crypto.test.ts` - Integration tests
|
|
131
|
-
|
|
132
|
-
## Verification
|
|
133
|
-
|
|
134
|
-
All requirements from task specification are met:
|
|
135
|
-
- ✅ Comprehensive tests for Web Crypto backend
|
|
136
|
-
- ✅ Tests work in both browsers and Node.js
|
|
137
|
-
- ✅ Performance tests included
|
|
138
|
-
- ✅ Consistency tests included
|
|
139
|
-
- ✅ Code coverage >= 90% achieved
|
|
140
|
-
- ✅ All tests pass successfully
|
package/WHATWG_STREAMS.md
DELETED
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
# WHATWG Streams Support
|
|
2
|
-
|
|
3
|
-
The `pure-md5` library now supports browser streams through WHATWG Streams API, allowing you to hash files, blobs, and readable streams in browser environments.
|
|
4
|
-
|
|
5
|
-
## Features
|
|
6
|
-
|
|
7
|
-
- **MD5ReadableStream**: A wrapper class that computes MD5 while reading from a ReadableStream
|
|
8
|
-
- **hashFile**: Hash a File object directly
|
|
9
|
-
- **hashBlob**: Hash a Blob object directly
|
|
10
|
-
- **hashReadableStream**: Hash any ReadableStream
|
|
11
|
-
- **MD5ReadableStream.hash**: Static method for hashing streams
|
|
12
|
-
|
|
13
|
-
## Usage
|
|
14
|
-
|
|
15
|
-
### Hashing a ReadableStream
|
|
16
|
-
|
|
17
|
-
```typescript
|
|
18
|
-
import { MD5ReadableStream } from 'pure-md5';
|
|
19
|
-
|
|
20
|
-
const source = new ReadableStream({
|
|
21
|
-
start(controller) {
|
|
22
|
-
controller.enqueue(new TextEncoder().encode('Hello World'));
|
|
23
|
-
controller.close();
|
|
24
|
-
}
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
const result = await MD5ReadableStream.hash(source);
|
|
28
|
-
console.log('MD5:', result.digest);
|
|
29
|
-
console.log('Bytes:', result.bytesProcessed);
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
### Hashing a File (Browser)
|
|
33
|
-
|
|
34
|
-
```typescript
|
|
35
|
-
import { hashFile } from 'pure-md5';
|
|
36
|
-
|
|
37
|
-
const input = document.querySelector('input[type="file"]');
|
|
38
|
-
input.addEventListener('change', async (e) => {
|
|
39
|
-
const file = (e.target as HTMLInputElement).files![0];
|
|
40
|
-
const result = await hashFile(file);
|
|
41
|
-
console.log('MD5:', result.digest);
|
|
42
|
-
});
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
### Hashing a Blob
|
|
46
|
-
|
|
47
|
-
```typescript
|
|
48
|
-
import { hashBlob } from 'pure-md5';
|
|
49
|
-
|
|
50
|
-
const canvas = document.querySelector('canvas');
|
|
51
|
-
canvas.toBlob(async (blob) => {
|
|
52
|
-
const result = await hashBlob(blob!);
|
|
53
|
-
console.log('MD5:', result.digest);
|
|
54
|
-
});
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
### Using MD5ReadableStream directly
|
|
58
|
-
|
|
59
|
-
```typescript
|
|
60
|
-
import { MD5ReadableStream, createMD5ReadableStream } from 'pure-md5';
|
|
61
|
-
|
|
62
|
-
// Using static hash method
|
|
63
|
-
const source = new ReadableStream({ ... });
|
|
64
|
-
const result = await MD5ReadableStream.hash(source);
|
|
65
|
-
|
|
66
|
-
// Using factory function
|
|
67
|
-
const stream = createMD5ReadableStream(source);
|
|
68
|
-
// Get reader to consume the stream
|
|
69
|
-
const reader = stream.getReader();
|
|
70
|
-
// MD5 result available via getResult()
|
|
71
|
-
const result = await stream.getResult();
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
### Processing with a reader
|
|
75
|
-
|
|
76
|
-
```typescript
|
|
77
|
-
const source = new ReadableStream({
|
|
78
|
-
start(controller) {
|
|
79
|
-
controller.enqueue(new TextEncoder().encode('test'));
|
|
80
|
-
controller.close();
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
const stream = new MD5ReadableStream(source);
|
|
85
|
-
const reader = stream.getReader();
|
|
86
|
-
|
|
87
|
-
while (true) {
|
|
88
|
-
const { done, value } = await reader.read();
|
|
89
|
-
if (done) break;
|
|
90
|
-
// Process chunks as they come
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Get MD5 result after consuming stream
|
|
94
|
-
const result = await stream.getResult();
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
## Options
|
|
98
|
-
|
|
99
|
-
All functions support an optional `MD5ReadableStreamOptions` parameter:
|
|
100
|
-
|
|
101
|
-
```typescript
|
|
102
|
-
interface MD5ReadableStreamOptions {
|
|
103
|
-
add32?: (x: number, y: number) => number; // Custom add32 function for testing
|
|
104
|
-
}
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
Example with custom add32:
|
|
108
|
-
|
|
109
|
-
```typescript
|
|
110
|
-
const customAdd32 = (x: number, y: number) => (x + y) & 0xffffffff;
|
|
111
|
-
const result = await hashFile(file, { add32: customAdd32 });
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
## API Reference
|
|
115
|
-
|
|
116
|
-
### MD5ReadableStream
|
|
117
|
-
|
|
118
|
-
#### Constructor
|
|
119
|
-
```typescript
|
|
120
|
-
new MD5ReadableStream(source: ReadableStream, options?: MD5ReadableStreamOptions)
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
#### Methods
|
|
124
|
-
|
|
125
|
-
- `getReader(): ReadableStreamDefaultReader<Uint8Array>` - Get a reader for the stream
|
|
126
|
-
- `getResult(): Promise<MD5Result>` - Get the MD5 result
|
|
127
|
-
- `getCurrentState(): { state: number[]; bytesProcessed: number }` - Get current internal state (for debugging)
|
|
128
|
-
- `getBytesProcessed(): number` - Get total bytes processed
|
|
129
|
-
|
|
130
|
-
#### Static Methods
|
|
131
|
-
|
|
132
|
-
- `hash(source: ReadableStream, options?: MD5ReadableStreamOptions): Promise<MD5Result>` - Hash a stream directly
|
|
133
|
-
|
|
134
|
-
### Factory Functions
|
|
135
|
-
|
|
136
|
-
- `createMD5ReadableStream(source: ReadableStream, options?: MD5ReadableStreamOptions): MD5ReadableStream`
|
|
137
|
-
|
|
138
|
-
### Hash Functions
|
|
139
|
-
|
|
140
|
-
- `hashFile(file: File, options?: MD5ReadableStreamOptions): Promise<MD5Result>` - Hash a File
|
|
141
|
-
- `hashBlob(blob: Blob, options?: MD5ReadableStreamOptions): Promise<MD5Result>` - Hash a Blob
|
|
142
|
-
|
|
143
|
-
### Result Type
|
|
144
|
-
|
|
145
|
-
```typescript
|
|
146
|
-
interface MD5Result {
|
|
147
|
-
digest: string; // MD5 hash as hex string (32 characters)
|
|
148
|
-
bytesProcessed: number; // Total bytes processed
|
|
149
|
-
}
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
## Browser Compatibility
|
|
153
|
-
|
|
154
|
-
Requires modern browsers with WHATWG Streams support:
|
|
155
|
-
- Chrome 52+
|
|
156
|
-
- Firefox 57+
|
|
157
|
-
- Safari 12.1+
|
|
158
|
-
- Edge 79+
|
|
159
|
-
|
|
160
|
-
For older browsers, consider using a [ReadableStream polyfill](https://github.com/whatwg/streams).
|
|
161
|
-
|
|
162
|
-
## Example: Upload Progress with MD5
|
|
163
|
-
|
|
164
|
-
```typescript
|
|
165
|
-
import { MD5ReadableStream } from 'pure-md5';
|
|
166
|
-
|
|
167
|
-
async function uploadWithHash(file: File): Promise<void> {
|
|
168
|
-
// Get file stream
|
|
169
|
-
const fileStream = file.stream();
|
|
170
|
-
|
|
171
|
-
// Create MD5 stream
|
|
172
|
-
const md5Stream = new MD5ReadableStream(fileStream);
|
|
173
|
-
|
|
174
|
-
// Get reader for progress tracking
|
|
175
|
-
const reader = md5Stream.getReader();
|
|
176
|
-
let bytesProcessed = 0;
|
|
177
|
-
|
|
178
|
-
while (true) {
|
|
179
|
-
const { done, value } = await reader.read();
|
|
180
|
-
if (done) break;
|
|
181
|
-
|
|
182
|
-
bytesProcessed += value.length;
|
|
183
|
-
const progress = (bytesProcessed / file.size * 100).toFixed(1);
|
|
184
|
-
console.log(`Upload progress: ${progress}%`);
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// Get MD5 hash
|
|
188
|
-
const result = await md5Stream.getResult();
|
|
189
|
-
console.log('Upload complete. MD5:', result.digest);
|
|
190
|
-
}
|
|
191
|
-
```
|
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for Node.js Crypto Backend
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { NodeCryptoBackend } from '../../src/adapters/node.js';
|
|
6
|
-
|
|
7
|
-
describe('NodeCryptoBackend', () => {
|
|
8
|
-
let backend: NodeCryptoBackend;
|
|
9
|
-
|
|
10
|
-
beforeAll(() => {
|
|
11
|
-
if (!NodeCryptoBackend.isAvailable()) {
|
|
12
|
-
console.log('Node.js Crypto not available, skipping tests');
|
|
13
|
-
pending('Node.js Crypto not available');
|
|
14
|
-
return;
|
|
15
|
-
}
|
|
16
|
-
backend = new NodeCryptoBackend();
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
describe('Basic hashing', () => {
|
|
20
|
-
it('should hash string correctly', async () => {
|
|
21
|
-
if (!backend) {
|
|
22
|
-
pending('Node.js Crypto not available');
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const result = await backend.hash('hello');
|
|
27
|
-
expect(result).toBe('5d41402abc4b2a76b9719d911017c592');
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it('should hash empty string', async () => {
|
|
31
|
-
if (!backend) {
|
|
32
|
-
pending('Node.js Crypto not available');
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const result = await backend.hash('');
|
|
37
|
-
expect(result).toBe('d41d8cd98f00b204e9800998ecf8427e');
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
it('should hash special characters', async () => {
|
|
41
|
-
if (!backend) {
|
|
42
|
-
pending('Node.js Crypto not available');
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const result = await backend.hash('!@#$%^&*()');
|
|
47
|
-
expect(result).toBe('05b28d17a7b6e7024b6e5d8cc43a8bf7');
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it('should hash unicode characters', async () => {
|
|
51
|
-
if (!backend) {
|
|
52
|
-
pending('Node.js Crypto not available');
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
const result = await backend.hash('Привет мир');
|
|
57
|
-
expect(result).toBe('79d636ccef972a9d10db69750cd53e8b');
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
it('should hash long string', async () => {
|
|
61
|
-
if (!backend) {
|
|
62
|
-
pending('Node.js Crypto not available');
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const longString = 'a'.repeat(10000);
|
|
67
|
-
const result = await backend.hash(longString);
|
|
68
|
-
expect(result.length).toBe(32);
|
|
69
|
-
});
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
describe('Binary data', () => {
|
|
73
|
-
it('should hash Uint8Array', async () => {
|
|
74
|
-
if (!backend) {
|
|
75
|
-
pending('Node.js Crypto not available');
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
const data = new Uint8Array([104, 101, 108, 108, 111]);
|
|
80
|
-
const result = await backend.hashBinary(data);
|
|
81
|
-
expect(result).toBe('5d41402abc4b2a76b9719d911017c592');
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
it('should hash ArrayBuffer', async () => {
|
|
85
|
-
if (!backend) {
|
|
86
|
-
pending('Node.js Crypto not available');
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const data = new TextEncoder().encode('hello').buffer;
|
|
91
|
-
const result = await backend.hashBinary(data);
|
|
92
|
-
expect(result).toBe('5d41402abc4b2a76b9719d911017c592');
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
it('should hash empty Uint8Array', async () => {
|
|
96
|
-
if (!backend) {
|
|
97
|
-
pending('Node.js Crypto not available');
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const data = new Uint8Array(0);
|
|
102
|
-
const result = await backend.hashBinary(data);
|
|
103
|
-
expect(result).toBe('d41d8cd98f00b204e9800998ecf8427e');
|
|
104
|
-
});
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
describe('Availability', () => {
|
|
108
|
-
it('should be available in Node.js', () => {
|
|
109
|
-
const available = NodeCryptoBackend.isAvailable();
|
|
110
|
-
expect(available).toBe(true);
|
|
111
|
-
});
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
describe('Performance', () => {
|
|
115
|
-
it('should hash 1MB data efficiently', async () => {
|
|
116
|
-
if (!backend) {
|
|
117
|
-
pending('Node.js Crypto not available');
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
const data = 'a'.repeat(1024 * 1024);
|
|
122
|
-
|
|
123
|
-
const start = Date.now();
|
|
124
|
-
const result = await backend.hash(data);
|
|
125
|
-
const duration = Date.now() - start;
|
|
126
|
-
|
|
127
|
-
expect(result.length).toBe(32);
|
|
128
|
-
expect(duration).toBeLessThan(500);
|
|
129
|
-
});
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
describe('Consistency', () => {
|
|
133
|
-
it('should produce same hash for same input', async () => {
|
|
134
|
-
if (!backend) {
|
|
135
|
-
pending('Node.js Crypto not available');
|
|
136
|
-
return;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
const input = 'test input';
|
|
140
|
-
const result1 = await backend.hash(input);
|
|
141
|
-
const result2 = await backend.hash(input);
|
|
142
|
-
expect(result1).toBe(result2);
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
it('should produce different hash for different inputs', async () => {
|
|
146
|
-
if (!backend) {
|
|
147
|
-
pending('Node.js Crypto not available');
|
|
148
|
-
return;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
const result1 = await backend.hash('hello');
|
|
152
|
-
const result2 = await backend.hash('world');
|
|
153
|
-
expect(result1).not.toBe(result2);
|
|
154
|
-
});
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
describe('Interface compliance', () => {
|
|
158
|
-
it('should have correct name and version', () => {
|
|
159
|
-
expect(backend.name).toBe('nodecrypto');
|
|
160
|
-
expect(backend.version).toBe('1.0.0');
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
it('should have reset method', () => {
|
|
164
|
-
expect(typeof backend.reset).toBe('function');
|
|
165
|
-
});
|
|
166
|
-
});
|
|
167
|
-
});
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for Web Crypto Backend in Node.js
|
|
3
|
-
* Only runs in Node.js 15+ with WebCrypto
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { WebCryptoBackend } from '../../src/adapters/webcrypto';
|
|
7
|
-
|
|
8
|
-
// Check if running in Node.js
|
|
9
|
-
const isNode =
|
|
10
|
-
typeof process !== 'undefined' &&
|
|
11
|
-
process.versions !== undefined &&
|
|
12
|
-
'node' in process.versions;
|
|
13
|
-
|
|
14
|
-
if (!isNode) {
|
|
15
|
-
console.log('Not in Node.js, skipping');
|
|
16
|
-
} else {
|
|
17
|
-
const nodeVersion = process.versions.node.split('.').map(Number);
|
|
18
|
-
const nodeMajor = nodeVersion[0];
|
|
19
|
-
const nodeMinor = nodeVersion[1] || 0;
|
|
20
|
-
|
|
21
|
-
// WebCrypto is available in Node.js 15+ (or 14.17+ with flag)
|
|
22
|
-
if (nodeMajor < 15 && !(nodeMajor === 14 && nodeMinor >= 17)) {
|
|
23
|
-
console.log(
|
|
24
|
-
`Node.js version ${process.versions.node} too low, skipping (need 15+ or 14.17+)`
|
|
25
|
-
);
|
|
26
|
-
} else {
|
|
27
|
-
describe('WebCryptoBackend in Node.js', () => {
|
|
28
|
-
let backend: WebCryptoBackend;
|
|
29
|
-
|
|
30
|
-
beforeAll(async () => {
|
|
31
|
-
const available = WebCryptoBackend.isAvailable();
|
|
32
|
-
if (!available) {
|
|
33
|
-
console.log('WebCrypto not available in Node.js, skipping');
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
backend = new WebCryptoBackend();
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
xit('should be available in Node.js', async () => {
|
|
40
|
-
const available = WebCryptoBackend.isAvailable();
|
|
41
|
-
expect(available).toBe(true);
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
it('should hash string correctly', async () => {
|
|
45
|
-
if (!backend) {
|
|
46
|
-
console.log('Skipping test: backend not initialized');
|
|
47
|
-
return;
|
|
48
|
-
}
|
|
49
|
-
const result = await backend.hash('hello');
|
|
50
|
-
expect(result).toBe('5d41402abc4b2a76b9719d911017c592');
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
it('should hash empty string', async () => {
|
|
54
|
-
if (!backend) {
|
|
55
|
-
console.log('Skipping test: backend not initialized');
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
const result = await backend.hash('');
|
|
59
|
-
expect(result).toBe('d41d8cd98f00b204e9800998ecf8427e');
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
it('should work with binary data', async () => {
|
|
63
|
-
if (!backend) {
|
|
64
|
-
console.log('Skipping test: backend not initialized');
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
const data = new Uint8Array([104, 101, 108, 108, 111]);
|
|
68
|
-
const result = await backend.hashBinary(data);
|
|
69
|
-
expect(result).toBe('5d41402abc4b2a76b9719d911017c592');
|
|
70
|
-
});
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
}
|