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,168 +0,0 @@
|
|
|
1
|
-
# Phase 3: Size Optimization and Tree-Shaking Configuration - Planning Summary
|
|
2
|
-
|
|
3
|
-
## Overview
|
|
4
|
-
|
|
5
|
-
A complete roadmap has been created for optimizing the pure-md5 library with migration to the modern tsup stack. The plan includes transitioning from the outdated Webpack+Babel+TypeScript to fast and efficient tsup.
|
|
6
|
-
|
|
7
|
-
## Task Structure
|
|
8
|
-
|
|
9
|
-
Total of 8 tasks, grouped by priorities:
|
|
10
|
-
|
|
11
|
-
### Priority 1: Migration to Modern Stack
|
|
12
|
-
|
|
13
|
-
1. **Task 1**: Migration from Webpack to tsup
|
|
14
|
-
- Install tsup and update TypeScript
|
|
15
|
-
- Remove outdated dependencies (Webpack, Babel)
|
|
16
|
-
- Configure tsup configuration
|
|
17
|
-
- Update package.json and scripts
|
|
18
|
-
|
|
19
|
-
2. **Task 6**: tsup Configuration for Different Formats
|
|
20
|
-
- Configurations for CommonJS, ES modules, UMD
|
|
21
|
-
- Minimal build with aggressive optimization
|
|
22
|
-
- Configure exports in package.json
|
|
23
|
-
|
|
24
|
-
### Priority 2: Code Optimization and Tree-Shaking
|
|
25
|
-
|
|
26
|
-
3. **Task 2**: Consolidation of Small Modules
|
|
27
|
-
- Combine ff/gg/hh/ii into round-functions.ts
|
|
28
|
-
- Combine hex and rhex
|
|
29
|
-
- Reduce file count from 16 to ~10
|
|
30
|
-
|
|
31
|
-
4. **Task 3**: Elimination of Code Duplication (add32)
|
|
32
|
-
- Remove inline definition from index.ts
|
|
33
|
-
- Single optimized implementation
|
|
34
|
-
|
|
35
|
-
5. **Task 4**: Moving Runtime Check to Compile-Time
|
|
36
|
-
- Remove MD5('hello') check from runtime
|
|
37
|
-
- Move check to tests
|
|
38
|
-
- Simplify md5 function
|
|
39
|
-
|
|
40
|
-
### Priority 3: Performance and Metrics
|
|
41
|
-
|
|
42
|
-
6. **Task 5**: Loop and Operation Optimization
|
|
43
|
-
- Optimize md51.ts, add32.ts, md5cycle.ts
|
|
44
|
-
- Improve memory handling
|
|
45
|
-
- Create performance tests
|
|
46
|
-
|
|
47
|
-
7. **Task 7**: Bundle Analysis and Metrics
|
|
48
|
-
- Bundle size measurement system
|
|
49
|
-
- Performance benchmarks
|
|
50
|
-
- TypeScript type quality check
|
|
51
|
-
- Tree-shaking effectiveness analysis
|
|
52
|
-
|
|
53
|
-
### Priority 4: Documentation and Infrastructure
|
|
54
|
-
|
|
55
|
-
8. **Task 8**: Documentation and CI/CD Update
|
|
56
|
-
- Update README and API documentation
|
|
57
|
-
- Configure GitHub Actions
|
|
58
|
-
- Code quality configurations
|
|
59
|
-
- Preparation for publication
|
|
60
|
-
|
|
61
|
-
## Critical Issues Identified During Analysis
|
|
62
|
-
|
|
63
|
-
### 1. Outdated Build Stack
|
|
64
|
-
|
|
65
|
-
- **Problem**: Webpack 4 + TypeScript 3.5 + Babel (2019)
|
|
66
|
-
- **Solution**: Migration to tsup (Task 1)
|
|
67
|
-
|
|
68
|
-
### 2. Dependency Redundancy
|
|
69
|
-
|
|
70
|
-
- **Problem**: 13 dev dependencies for a simple library
|
|
71
|
-
- **Solution**: Reduction to 3-5 packages with tsup
|
|
72
|
-
|
|
73
|
-
### 3. Slow Build
|
|
74
|
-
|
|
75
|
-
- **Problem**: Webpack + Babel slow transpilation
|
|
76
|
-
- **Solution**: tsup is 10-100 times faster
|
|
77
|
-
|
|
78
|
-
### 4. Poor Tree-Shaking Due to CommonJS
|
|
79
|
-
|
|
80
|
-
- **Problem**: `module: "commonjs"` in tsconfig.json
|
|
81
|
-
- **Solution**: ES modules + native tree-shaking in tsup
|
|
82
|
-
|
|
83
|
-
### 5. Runtime Overhead
|
|
84
|
-
|
|
85
|
-
- **Problem**: `hex(md51('hello'))` check on every import
|
|
86
|
-
- **Solution**: Move to compile-time (Task 4)
|
|
87
|
-
|
|
88
|
-
### 6. Code Duplication
|
|
89
|
-
|
|
90
|
-
- **Problem**: `add32` defined in two places
|
|
91
|
-
- **Solution**: Eliminate duplication (Task 3)
|
|
92
|
-
|
|
93
|
-
## Expected Results
|
|
94
|
-
|
|
95
|
-
### Quantitative Metrics
|
|
96
|
-
|
|
97
|
-
1. **Build speed**: 10-100x acceleration
|
|
98
|
-
2. **Bundle size**: 20-30% reduction
|
|
99
|
-
3. **Dev dependencies**: From 13 to 3-5 packages
|
|
100
|
-
4. **Performance**: 10-20% improvement
|
|
101
|
-
5. **File count**: From 16 to ~10
|
|
102
|
-
|
|
103
|
-
### Qualitative Improvements
|
|
104
|
-
|
|
105
|
-
1. **Modern stack**: tsup + TypeScript 5+
|
|
106
|
-
2. **Better tree-shaking**: Native support in tsup
|
|
107
|
-
3. **Flexible builds**: CommonJS, ES modules, UMD, minimal
|
|
108
|
-
4. **Professional infrastructure**: CI/CD, documentation, tests
|
|
109
|
-
5. **Improved developer experience**: Fast builds, watch mode
|
|
110
|
-
|
|
111
|
-
## Execution Order
|
|
112
|
-
|
|
113
|
-
Recommended task execution order:
|
|
114
|
-
|
|
115
|
-
1. **Task 1** → **Task 6** (migration to tsup and format configuration)
|
|
116
|
-
2. **Task 2** → **Task 3** → **Task 4** (code optimization)
|
|
117
|
-
3. **Task 5** → **Task 7** (performance and metrics)
|
|
118
|
-
4. **Task 8** (documentation and infrastructure)
|
|
119
|
-
|
|
120
|
-
## Risks and Mitigation
|
|
121
|
-
|
|
122
|
-
### Risk 1: Breaking Backward Compatibility
|
|
123
|
-
|
|
124
|
-
- **Mitigation**: Preserving all formats (CommonJS, ES modules, UMD)
|
|
125
|
-
- **Mitigation**: Thorough testing of all use cases
|
|
126
|
-
|
|
127
|
-
### Risk 2: Issues with .d.ts File Generation
|
|
128
|
-
|
|
129
|
-
- **Mitigation**: tsup has built-in d.ts support
|
|
130
|
-
- **Mitigation**: Check with @arethetypeswrong/cli
|
|
131
|
-
|
|
132
|
-
### Risk 3: Incompatibility with Existing Consumers
|
|
133
|
-
|
|
134
|
-
- **Mitigation**: Preserving current API
|
|
135
|
-
- **Mitigation**: Semantic versioning (major version for breaking changes)
|
|
136
|
-
|
|
137
|
-
### Risk 4: Difficulty Debugging Minified Code
|
|
138
|
-
|
|
139
|
-
- **Mitigation**: Source maps for development builds
|
|
140
|
-
- **Mitigation**: Separate builds for development and production
|
|
141
|
-
|
|
142
|
-
## Next Steps After Phase 3
|
|
143
|
-
|
|
144
|
-
After successful optimization completion:
|
|
145
|
-
|
|
146
|
-
1. **Phase 4**: File system integration
|
|
147
|
-
2. **Phase 5**: WHATWG Streams support
|
|
148
|
-
3. **Phase 6**: Comprehensive testing and documentation
|
|
149
|
-
4. **Phase 7**: Architectural integration
|
|
150
|
-
|
|
151
|
-
## Status
|
|
152
|
-
|
|
153
|
-
- **Planning**: Completed ✅
|
|
154
|
-
- **Implementation**: Awaiting start
|
|
155
|
-
- **Testing**: Awaiting implementation
|
|
156
|
-
- **Documentation**: Partially ready
|
|
157
|
-
|
|
158
|
-
## Responsible Parties
|
|
159
|
-
|
|
160
|
-
- AI Agent: Task implementation
|
|
161
|
-
- Maintainer: Review and integration
|
|
162
|
-
- CI/CD: Automatic testing and benchmarks
|
|
163
|
-
|
|
164
|
-
## Investment
|
|
165
|
-
|
|
166
|
-
**Time estimate:** 8-16 hours for all tasks
|
|
167
|
-
**Timeline:** 2-3 days with full-time work
|
|
168
|
-
**ROI:** High (accelerated development, reduced maintenance cost)
|
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
# Task 03: Web Crypto API Adapter Implementation
|
|
2
|
-
|
|
3
|
-
## Goal
|
|
4
|
-
|
|
5
|
-
Создать адаптер для использования Web Crypto API (Crypto.subtle.digest) для вычисления MD5 хеша.
|
|
6
|
-
|
|
7
|
-
## Requirements
|
|
8
|
-
|
|
9
|
-
- Support Web Crypto API в современных браузерах и Node.js 15+
|
|
10
|
-
- Обработка строк и бинарных данных
|
|
11
|
-
- Integration с единым интерфейсом MD5Backend
|
|
12
|
-
|
|
13
|
-
## Implementation
|
|
14
|
-
|
|
15
|
-
### 1. Создать файл src/adapters/web-crypto.ts
|
|
16
|
-
|
|
17
|
-
```typescript
|
|
18
|
-
export class WebCryptoBackend implements MD5Backend {
|
|
19
|
-
static name = 'webcrypto';
|
|
20
|
-
static version = '1.0.0';
|
|
21
|
-
|
|
22
|
-
async hash(data: string): Promise<string> {
|
|
23
|
-
if (!await this.isAvailable()) {
|
|
24
|
-
throw new Error('Web Crypto API is not available');
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const encoder = new TextEncoder();
|
|
28
|
-
const buffer = encoder.encode(data);
|
|
29
|
-
const hashBuffer = await crypto.subtle.digest('MD5', buffer);
|
|
30
|
-
return this.bufferToHex(hashBuffer);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
async hashBinary(data: ArrayBuffer | Uint8Array): Promise<string> {
|
|
34
|
-
if (!await this.isAvailable()) {
|
|
35
|
-
throw new Error('Web Crypto API is not available');
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const buffer = data instanceof Uint8Array
|
|
39
|
-
? data.buffer
|
|
40
|
-
: data;
|
|
41
|
-
const hashBuffer = await crypto.subtle.digest('MD5', buffer);
|
|
42
|
-
return this.bufferToHex(hashBuffer);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
static async isAvailable(): Promise<boolean> {
|
|
46
|
-
if (typeof crypto === 'undefined' || crypto === null) {
|
|
47
|
-
return false;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
if (typeof crypto.subtle === 'undefined' || crypto.subtle === null) {
|
|
51
|
-
return false;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
try {
|
|
55
|
-
return typeof crypto.subtle.digest === 'function';
|
|
56
|
-
} catch {
|
|
57
|
-
return false;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
private bufferToHex(buffer: ArrayBuffer): string {
|
|
62
|
-
const bytes = new Uint8Array(buffer);
|
|
63
|
-
return Array.from(bytes)
|
|
64
|
-
.map(b => b.toString(16).padStart(2, '0'))
|
|
65
|
-
.join('');
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
### 2. Tests
|
|
71
|
-
|
|
72
|
-
Создать файл `__tests__/adapters/web-crypto.test.ts`:
|
|
73
|
-
|
|
74
|
-
```typescript
|
|
75
|
-
describe('WebCryptoBackend', () => {
|
|
76
|
-
let backend: WebCryptoBackend;
|
|
77
|
-
|
|
78
|
-
beforeAll(async () => {
|
|
79
|
-
if (!await WebCryptoBackend.isAvailable()) {
|
|
80
|
-
console.log('Web Crypto API not available, skipping tests');
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
backend = new WebCryptoBackend();
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
it('should hash string correctly', async () => {
|
|
87
|
-
const result = await backend.hash('hello');
|
|
88
|
-
expect(result).toBe('5d41402abc4b2a76b9719d911017c592');
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
it('should hash empty string', async () => {
|
|
92
|
-
const result = await backend.hash('');
|
|
93
|
-
expect(result).toBe('d41d8cd98f00b204e9800998ecf8427e');
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
it('should hash binary data', async () => {
|
|
97
|
-
const data = new Uint8Array([104, 101, 108, 108, 111]); // "hello"
|
|
98
|
-
const result = await backend.hashBinary(data);
|
|
99
|
-
expect(result).toBe('5d41402abc4b2a76b9719d911017c592');
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
it('should be available in modern browsers', async () => {
|
|
103
|
-
const available = await WebCryptoBackend.isAvailable();
|
|
104
|
-
expect(available).toBe(true);
|
|
105
|
-
});
|
|
106
|
-
});
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
### 3. Integration с основным кодом
|
|
110
|
-
|
|
111
|
-
В `src/adapters/index.ts`:
|
|
112
|
-
|
|
113
|
-
```typescript
|
|
114
|
-
export { WebCryptoBackend } from './web-crypto.js';
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
### 4. Conditional exports
|
|
118
|
-
|
|
119
|
-
В `package.json`:
|
|
120
|
-
|
|
121
|
-
```json
|
|
122
|
-
{
|
|
123
|
-
"exports": {
|
|
124
|
-
"./adapters/webcrypto": {
|
|
125
|
-
"types": "./dist/adapters/web-crypto.d.ts",
|
|
126
|
-
"import": "./dist/adapters/web-crypto.js"
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
### 5. Checking в браузере и Node.js
|
|
133
|
-
|
|
134
|
-
Тестирование в различных окружениях:
|
|
135
|
-
|
|
136
|
-
```bash
|
|
137
|
-
# Browsers
|
|
138
|
-
npm run test:browser
|
|
139
|
-
|
|
140
|
-
# Node.js 15+
|
|
141
|
-
node --experimental-global-crypto --experimental-wasm-threads test.js
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
## Ожидаемый результат
|
|
145
|
-
|
|
146
|
-
- ✅ WebCryptoBackend реализован
|
|
147
|
-
- ✅ Tests проходят успешно
|
|
148
|
-
- ✅ Интегрирован в общую систему адаптеров
|
|
149
|
-
- ✅ Документирован usage
|
|
@@ -1,181 +0,0 @@
|
|
|
1
|
-
# Task 04: Node.js Crypto Adapter Implementation
|
|
2
|
-
|
|
3
|
-
## Goal
|
|
4
|
-
|
|
5
|
-
Создать адаптер для использования нативного `node:crypto` модуля для вычисления MD5 хеша.
|
|
6
|
-
|
|
7
|
-
## Requirements
|
|
8
|
-
|
|
9
|
-
- Support Node.js crypto API (версии 10+)
|
|
10
|
-
- Обработка строк и бинарных данных
|
|
11
|
-
- Потоковая обработка через update/digest
|
|
12
|
-
- Integration с единым интерфейсом MD5Backend
|
|
13
|
-
|
|
14
|
-
## Implementation
|
|
15
|
-
|
|
16
|
-
### 1. Создать файл src/adapters/node-crypto.ts
|
|
17
|
-
|
|
18
|
-
```typescript
|
|
19
|
-
export class NodeCryptoBackend implements MD5Backend {
|
|
20
|
-
static name = 'nodecrypto';
|
|
21
|
-
static version = '1.0.0';
|
|
22
|
-
|
|
23
|
-
private hashInstance: import('node:crypto').Hash | null = null;
|
|
24
|
-
|
|
25
|
-
hash(data: string): string {
|
|
26
|
-
if (!this.isAvailable()) {
|
|
27
|
-
throw new Error('Node.js Crypto is not available');
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const crypto = require('node:crypto');
|
|
31
|
-
return crypto.createHash('md5').update(data).digest('hex');
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
hashBinary(data: ArrayBuffer | Uint8Array): string {
|
|
35
|
-
if (!this.isAvailable()) {
|
|
36
|
-
throw new Error('Node.js Crypto is not available');
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const crypto = require('node:crypto');
|
|
40
|
-
const buffer = data instanceof Uint8Array
|
|
41
|
-
? data
|
|
42
|
-
: Buffer.from(data);
|
|
43
|
-
return crypto.createHash('md5').update(buffer).digest('hex');
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
update(data: string | ArrayBuffer | Uint8Array): void {
|
|
47
|
-
if (!this.hashInstance) {
|
|
48
|
-
const crypto = require('node:crypto');
|
|
49
|
-
this.hashInstance = crypto.createHash('md5');
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
if (data instanceof ArrayBuffer) {
|
|
53
|
-
this.hashInstance.update(Buffer.from(data));
|
|
54
|
-
} else if (data instanceof Uint8Array) {
|
|
55
|
-
this.hashInstance.update(data);
|
|
56
|
-
} else {
|
|
57
|
-
this.hashInstance.update(data);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
digest(encoding: 'hex' | 'buffer' = 'hex'): string | Uint8Array {
|
|
62
|
-
if (!this.hashInstance) {
|
|
63
|
-
return encoding === 'hex' ? '' : new Uint8Array(0);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return encoding === 'hex'
|
|
67
|
-
? this.hashInstance.digest('hex')
|
|
68
|
-
: this.hashInstance.digest();
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
reset(): void {
|
|
72
|
-
this.hashInstance = null;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
static isAvailable(): boolean {
|
|
76
|
-
try {
|
|
77
|
-
const crypto = require('node:crypto');
|
|
78
|
-
return typeof crypto.createHash === 'function';
|
|
79
|
-
} catch {
|
|
80
|
-
return false;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
### 2. Tests
|
|
87
|
-
|
|
88
|
-
Создать файл `__tests__/adapters/node-crypto.test.ts`:
|
|
89
|
-
|
|
90
|
-
```typescript
|
|
91
|
-
describe('NodeCryptoBackend', () => {
|
|
92
|
-
let backend: NodeCryptoBackend;
|
|
93
|
-
|
|
94
|
-
beforeAll(() => {
|
|
95
|
-
if (!NodeCryptoBackend.isAvailable()) {
|
|
96
|
-
console.log('Node.js Crypto not available, skipping tests');
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
backend = new NodeCryptoBackend();
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
it('should hash string correctly', () => {
|
|
103
|
-
const result = backend.hash('hello');
|
|
104
|
-
expect(result).toBe('5d41402abc4b2a76b9719d911017c592');
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
it('should hash empty string', () => {
|
|
108
|
-
const result = backend.hash('');
|
|
109
|
-
expect(result).toBe('d41d8cd98f00b204e9800998ecf8427e');
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
it('should hash binary data', () => {
|
|
113
|
-
const data = new Uint8Array([104, 101, 108, 108, 111]); // "hello"
|
|
114
|
-
const result = backend.hashBinary(data);
|
|
115
|
-
expect(result).toBe('5d41402abc4b2a76b9719d911017c592');
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
it('should support streaming via update/digest', () => {
|
|
119
|
-
backend.update('he');
|
|
120
|
-
backend.update('l');
|
|
121
|
-
backend.update('lo');
|
|
122
|
-
const result = backend.digest('hex');
|
|
123
|
-
expect(result).toBe('5d41402abc4b2a76b9719d911017c592');
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
it('should reset state', () => {
|
|
127
|
-
backend.update('hello');
|
|
128
|
-
backend.reset();
|
|
129
|
-
backend.update('world');
|
|
130
|
-
const result = backend.digest('hex');
|
|
131
|
-
expect(result).toBe('5d41402abc4b2a76b9719d911017c592'); // "world" hash
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
it('should be available in Node.js', () => {
|
|
135
|
-
const available = NodeCryptoBackend.isAvailable();
|
|
136
|
-
expect(available).toBe(true);
|
|
137
|
-
});
|
|
138
|
-
});
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
### 3. Integration с основным кодом
|
|
142
|
-
|
|
143
|
-
В `src/adapters/index.ts`:
|
|
144
|
-
|
|
145
|
-
```typescript
|
|
146
|
-
export { NodeCryptoBackend } from './node-crypto.js';
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
### 4. Conditional exports
|
|
150
|
-
|
|
151
|
-
В `package.json`:
|
|
152
|
-
|
|
153
|
-
```json
|
|
154
|
-
{
|
|
155
|
-
"exports": {
|
|
156
|
-
"./adapters/node": {
|
|
157
|
-
"types": "./dist/adapters/node-crypto.d.ts",
|
|
158
|
-
"import": "./dist/adapters/node-crypto.js",
|
|
159
|
-
"require": "./dist/adapters/node-crypto.cjs"
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
### 5. Support CommonJS
|
|
166
|
-
|
|
167
|
-
Для совместимости с CommonJS добавить `src/adapters/node-crypto.cjs`:
|
|
168
|
-
|
|
169
|
-
```javascript
|
|
170
|
-
'use strict';
|
|
171
|
-
const { NodeCryptoBackend } = require('./node-crypto.js');
|
|
172
|
-
module.exports = { NodeCryptoBackend };
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
## Ожидаемый результат
|
|
176
|
-
|
|
177
|
-
- ✅ NodeCryptoBackend реализован
|
|
178
|
-
- ✅ Support потоковой обработки (update/digest)
|
|
179
|
-
- ✅ Tests проходят успешно
|
|
180
|
-
- ✅ Интегрирован в общую систему адаптеров
|
|
181
|
-
- ✅ Документирован usage
|
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
# Task 05: Рефакторинг Pure JS кода в адаптер
|
|
2
|
-
|
|
3
|
-
## Goal
|
|
4
|
-
|
|
5
|
-
Преобразовать существующую реализацию MD5 в адаптер, соответствующий интерфейсу MD5Backend.
|
|
6
|
-
|
|
7
|
-
## Текущая структура
|
|
8
|
-
|
|
9
|
-
Текущий код находится в `src/`:
|
|
10
|
-
- `src/index.ts` - главная функция md5
|
|
11
|
-
- `src/md51.ts` - обработка сообщений
|
|
12
|
-
- `src/md5blk.ts` - обработка блоков
|
|
13
|
-
- `src/md5cycle.ts` - цикл MD5
|
|
14
|
-
- `src/round-functions.ts` - функции раунда
|
|
15
|
-
- и т.д.
|
|
16
|
-
|
|
17
|
-
## Рефакторинг
|
|
18
|
-
|
|
19
|
-
### 1. Создать файл src/adapters/pure-js.ts
|
|
20
|
-
|
|
21
|
-
```typescript
|
|
22
|
-
import { hex, md51 } from '../index.js';
|
|
23
|
-
|
|
24
|
-
export class PureJSBackend implements MD5Backend {
|
|
25
|
-
static name = 'purejs';
|
|
26
|
-
static version = '0.1.0';
|
|
27
|
-
|
|
28
|
-
private state: {
|
|
29
|
-
data: string;
|
|
30
|
-
finished: boolean;
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
constructor() {
|
|
34
|
-
this.state = { data: '', finished: false };
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
hash(data: string): string {
|
|
38
|
-
return md51(data);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
hashBinary(data: ArrayBuffer | Uint8Array): string {
|
|
42
|
-
const text = data instanceof ArrayBuffer
|
|
43
|
-
? new TextDecoder().decode(data)
|
|
44
|
-
: new TextDecoder().decode(data);
|
|
45
|
-
return md51(text);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
update(data: string | ArrayBuffer | Uint8Array): void {
|
|
49
|
-
if (this.state.finished) {
|
|
50
|
-
// Reset if already finished
|
|
51
|
-
this.state = { data: '', finished: false };
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if (data instanceof ArrayBuffer) {
|
|
55
|
-
this.state.data += new TextDecoder().decode(data);
|
|
56
|
-
} else if (data instanceof Uint8Array) {
|
|
57
|
-
this.state.data += new TextDecoder().decode(data);
|
|
58
|
-
} else {
|
|
59
|
-
this.state.data += data;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
digest(encoding: 'hex' | 'buffer' = 'hex'): string | Uint8Array {
|
|
64
|
-
const result = md51(this.state.data);
|
|
65
|
-
this.state.finished = true;
|
|
66
|
-
|
|
67
|
-
if (encoding === 'buffer') {
|
|
68
|
-
return this.hexToBuffer(result);
|
|
69
|
-
}
|
|
70
|
-
return result;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
reset(): void {
|
|
74
|
-
this.state = { data: '', finished: false };
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
static isAvailable(): boolean {
|
|
78
|
-
return true; // Always available
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
private hexToBuffer(hex: string): Uint8Array {
|
|
82
|
-
const bytes = [];
|
|
83
|
-
for (let i = 0; i < hex.length; i += 2) {
|
|
84
|
-
bytes.push(parseInt(hex.substring(i, i + 2), 16));
|
|
85
|
-
}
|
|
86
|
-
return new Uint8Array(bytes);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
### 2. Checking текущей реализации
|
|
92
|
-
|
|
93
|
-
Убедиться, что `md51` работает корректно:
|
|
94
|
-
|
|
95
|
-
```typescript
|
|
96
|
-
// Test from __tests__/md51.test.ts
|
|
97
|
-
it('should hash "hello" correctly', () => {
|
|
98
|
-
expect(md51('hello')).toBe('5d41402abc4b2a76b9719d911017c592');
|
|
99
|
-
});
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
### 3. Integration с адаптерами
|
|
103
|
-
|
|
104
|
-
В `src/adapters/index.ts`:
|
|
105
|
-
|
|
106
|
-
```typescript
|
|
107
|
-
export { PureJSBackend } from './pure-js.js';
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
### 4. Conditional exports
|
|
111
|
-
|
|
112
|
-
В `package.json`:
|
|
113
|
-
|
|
114
|
-
```json
|
|
115
|
-
{
|
|
116
|
-
"exports": {
|
|
117
|
-
"./adapters/purejs": {
|
|
118
|
-
"types": "./dist/adapters/pure-js.d.ts",
|
|
119
|
-
"import": "./dist/adapters/pure-js.js"
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
### 5. Tests
|
|
126
|
-
|
|
127
|
-
Создать файл `__tests__/adapters/pure-js.test.ts`:
|
|
128
|
-
|
|
129
|
-
```typescript
|
|
130
|
-
describe('PureJSBackend', () => {
|
|
131
|
-
let backend: PureJSBackend;
|
|
132
|
-
|
|
133
|
-
beforeAll(() => {
|
|
134
|
-
backend = new PureJSBackend();
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
it('should hash string correctly', () => {
|
|
138
|
-
const result = backend.hash('hello');
|
|
139
|
-
expect(result).toBe('5d41402abc4b2a76b9719d911017c592');
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
it('should hash empty string', () => {
|
|
143
|
-
const result = backend.hash('');
|
|
144
|
-
expect(result).toBe('d41d8cd98f00b204e9800998ecf8427e');
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
it('should hash binary data', () => {
|
|
148
|
-
const data = new Uint8Array([104, 101, 108, 108, 111]); // "hello"
|
|
149
|
-
const result = backend.hashBinary(data);
|
|
150
|
-
expect(result).toBe('5d41402abc4b2a76b9719d911017c592');
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
it('should support streaming via update/digest', () => {
|
|
154
|
-
backend.update('he');
|
|
155
|
-
backend.update('l');
|
|
156
|
-
backend.update('lo');
|
|
157
|
-
const result = backend.digest('hex');
|
|
158
|
-
expect(result).toBe('5d41402abc4b2a76b9719d911017c592');
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
it('should be always available', () => {
|
|
162
|
-
const available = PureJSBackend.isAvailable();
|
|
163
|
-
expect(available).toBe(true);
|
|
164
|
-
});
|
|
165
|
-
});
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
## Ожидаемый результат
|
|
169
|
-
|
|
170
|
-
- ✅ PureJSBackend реализован из существующего кода
|
|
171
|
-
- ✅ Сохранена совместимость с текущим API
|
|
172
|
-
- ✅ Support потоковой обработки (update/digest)
|
|
173
|
-
- ✅ Tests проходят успешно
|
|
174
|
-
- ✅ Интегрирован в общую систему адаптеров
|