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,158 +0,0 @@
|
|
|
1
|
-
# Task 06: Support for Internet Explorer 11 (msCrypto)
|
|
2
|
-
|
|
3
|
-
## Goal
|
|
4
|
-
|
|
5
|
-
Создать адаптер для использования устаревшего `window.msCrypto` в Internet Explorer 11.
|
|
6
|
-
|
|
7
|
-
## Важные замечания
|
|
8
|
-
|
|
9
|
-
- IE11 поддерживает только подмножество Web Crypto API
|
|
10
|
-
- Некоторые алгоритмы могут отличаться
|
|
11
|
-
- Проверить совместимость с MD5
|
|
12
|
-
|
|
13
|
-
## Implementation
|
|
14
|
-
|
|
15
|
-
### 1. Создать файл src/adapters/ie11.ts
|
|
16
|
-
|
|
17
|
-
```typescript
|
|
18
|
-
export class IE11Backend implements MD5Backend {
|
|
19
|
-
static name = 'ie11';
|
|
20
|
-
static version = '1.0.0';
|
|
21
|
-
|
|
22
|
-
private crypto: Crypto;
|
|
23
|
-
private algorithm: string = 'MD5';
|
|
24
|
-
|
|
25
|
-
constructor() {
|
|
26
|
-
if (!this.isAvailable()) {
|
|
27
|
-
throw new Error('IE11 Crypto is not available');
|
|
28
|
-
}
|
|
29
|
-
this.crypto = (window as any).msCrypto;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
async hash(data: string): Promise<string> {
|
|
33
|
-
const encoder = new TextEncoder();
|
|
34
|
-
const buffer = encoder.encode(data);
|
|
35
|
-
const hashBuffer = await this.crypto.subtle.digest(this.algorithm, buffer);
|
|
36
|
-
return this.bufferToHex(hashBuffer);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
async hashBinary(data: ArrayBuffer | Uint8Array): Promise<string> {
|
|
40
|
-
const buffer = data instanceof Uint8Array
|
|
41
|
-
? data.buffer
|
|
42
|
-
: data;
|
|
43
|
-
const hashBuffer = await this.crypto.subtle.digest(this.algorithm, buffer);
|
|
44
|
-
return this.bufferToHex(hashBuffer);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
static async isAvailable(): Promise<boolean> {
|
|
48
|
-
if (typeof window === 'undefined') {
|
|
49
|
-
return false;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const msCrypto = (window as any).msCrypto;
|
|
53
|
-
if (!msCrypto) {
|
|
54
|
-
return false;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
if (!msCrypto.subtle) {
|
|
58
|
-
return false;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
try {
|
|
62
|
-
// Checking поддержки MD5
|
|
63
|
-
const testBuffer = new Uint8Array([1, 2, 3, 4]);
|
|
64
|
-
await msCrypto.subtle.digest('MD5', testBuffer);
|
|
65
|
-
return true;
|
|
66
|
-
} catch {
|
|
67
|
-
return false;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
private bufferToHex(buffer: ArrayBuffer): string {
|
|
72
|
-
const bytes = new Uint8Array(buffer);
|
|
73
|
-
return Array.from(bytes)
|
|
74
|
-
.map(b => b.toString(16).padStart(2, '0'))
|
|
75
|
-
.join('');
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
### 2. Tests
|
|
81
|
-
|
|
82
|
-
Создать файл `__tests__/adapters/ie11.test.ts`:
|
|
83
|
-
|
|
84
|
-
```typescript
|
|
85
|
-
describe('IE11Backend', () => {
|
|
86
|
-
let backend: IE11Backend;
|
|
87
|
-
|
|
88
|
-
beforeAll(async () => {
|
|
89
|
-
if (!await IE11Backend.isAvailable()) {
|
|
90
|
-
console.log('IE11 Crypto not available, skipping tests');
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
backend = new IE11Backend();
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
it('should hash string correctly', async () => {
|
|
97
|
-
const result = await backend.hash('hello');
|
|
98
|
-
expect(result).toBe('5d41402abc4b2a76b9719d911017c592');
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
it('should hash empty string', async () => {
|
|
102
|
-
const result = await backend.hash('');
|
|
103
|
-
expect(result).toBe('d41d8cd98f00b204e9800998ecf8427e');
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
it('should be available in IE11', async () => {
|
|
107
|
-
const available = await IE11Backend.isAvailable();
|
|
108
|
-
// В реальных тестах этот тест будет пропущен в modern browsers
|
|
109
|
-
if (available) {
|
|
110
|
-
expect(true).toBe(true);
|
|
111
|
-
}
|
|
112
|
-
});
|
|
113
|
-
});
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
### 3. Integration
|
|
117
|
-
|
|
118
|
-
В `src/adapters/index.ts`:
|
|
119
|
-
|
|
120
|
-
```typescript
|
|
121
|
-
export { IE11Backend } from './ie11.js';
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
### 4. Conditional exports
|
|
125
|
-
|
|
126
|
-
В `package.json`:
|
|
127
|
-
|
|
128
|
-
```json
|
|
129
|
-
{
|
|
130
|
-
"exports": {
|
|
131
|
-
"./adapters/ie11": {
|
|
132
|
-
"types": "./dist/adapters/ie11.d.ts",
|
|
133
|
-
"import": "./dist/adapters/ie11.js"
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
### 5. Обработка ошибок
|
|
140
|
-
|
|
141
|
-
В IE11 могут возникнуть ошибки, поэтому обернуть в try-catch:
|
|
142
|
-
|
|
143
|
-
```typescript
|
|
144
|
-
try {
|
|
145
|
-
const backend = new IE11Backend();
|
|
146
|
-
const result = await backend.hash('data');
|
|
147
|
-
} catch (error) {
|
|
148
|
-
console.warn('IE11 backend failed:', error);
|
|
149
|
-
// Fallback to pure JS
|
|
150
|
-
}
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
## Ожидаемый результат
|
|
154
|
-
|
|
155
|
-
- ✅ IE11Backend реализован
|
|
156
|
-
- ✅ Tests проходят успешно (если IE11 доступен)
|
|
157
|
-
- ✅ Интегрирован в общую систему адаптеров
|
|
158
|
-
- ✅ Обработка ошибок при отсутствии поддержки
|
|
@@ -1,232 +0,0 @@
|
|
|
1
|
-
# Task 07: Environment Detection and Available Backends Implementation
|
|
2
|
-
|
|
3
|
-
## Goal
|
|
4
|
-
|
|
5
|
-
Создать систему обнаружения окружения (браузер, Node.js) и проверки доступности backend'ов.
|
|
6
|
-
|
|
7
|
-
## Implementation
|
|
8
|
-
|
|
9
|
-
### 1. Создать файл src/detection/environment.ts
|
|
10
|
-
|
|
11
|
-
```typescript
|
|
12
|
-
export enum RuntimeEnvironment {
|
|
13
|
-
BROWSER = 'browser',
|
|
14
|
-
NODE = 'node',
|
|
15
|
-
WEBWORKER = 'webworker',
|
|
16
|
-
UNKNOWN = 'unknown'
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function detectEnvironment(): RuntimeEnvironment {
|
|
20
|
-
// Check Node.js environment
|
|
21
|
-
if (typeof process !== 'undefined' && process.versions && process.versions.node) {
|
|
22
|
-
return RuntimeEnvironment.NODE;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// Check web worker
|
|
26
|
-
if (typeof importScripts !== 'undefined') {
|
|
27
|
-
return RuntimeEnvironment.WEBWORKER;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// Check browser
|
|
31
|
-
if (typeof window !== 'undefined' && window.document) {
|
|
32
|
-
return RuntimeEnvironment.BROWSER;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
return RuntimeEnvironment.UNKNOWN;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export function isNode(): boolean {
|
|
39
|
-
return typeof process !== 'undefined' &&
|
|
40
|
-
process.versions !== undefined &&
|
|
41
|
-
'node' in process.versions;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export function isBrowser(): boolean {
|
|
45
|
-
return typeof window !== 'undefined' &&
|
|
46
|
-
typeof document !== 'undefined';
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export function isWebWorker(): boolean {
|
|
50
|
-
return typeof importScripts !== 'undefined';
|
|
51
|
-
}
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
### 2. Checking конкретных backend'ов
|
|
55
|
-
|
|
56
|
-
Создать файл `src/detection/backend-availability.ts`:
|
|
57
|
-
|
|
58
|
-
```typescript
|
|
59
|
-
import { PureJSBackend } from '../adapters/pure-js.js';
|
|
60
|
-
import { WebCryptoBackend } from '../adapters/web-crypto.js';
|
|
61
|
-
import { NodeCryptoBackend } from '../adapters/node-crypto.js';
|
|
62
|
-
import { IE11Backend } from '../adapters/ie11.js';
|
|
63
|
-
|
|
64
|
-
export interface BackendAvailability {
|
|
65
|
-
backend: string;
|
|
66
|
-
available: boolean;
|
|
67
|
-
reason?: string;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export async function checkBackendAvailability(backend: string): Promise<BackendAvailability> {
|
|
71
|
-
switch (backend) {
|
|
72
|
-
case 'webcrypto':
|
|
73
|
-
const webCryptoAvailable = await WebCryptoBackend.isAvailable();
|
|
74
|
-
return {
|
|
75
|
-
backend: 'webcrypto',
|
|
76
|
-
available: webCryptoAvailable,
|
|
77
|
-
reason: webCryptoAvailable ? undefined : 'Web Crypto API not available'
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
case 'nodecrypto':
|
|
81
|
-
const nodeCryptoAvailable = NodeCryptoBackend.isAvailable();
|
|
82
|
-
return {
|
|
83
|
-
backend: 'nodecrypto',
|
|
84
|
-
available: nodeCryptoAvailable,
|
|
85
|
-
reason: nodeCryptoAvailable ? undefined : 'Node.js crypto not available'
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
case 'ie11':
|
|
89
|
-
const ie11Available = await IE11Backend.isAvailable();
|
|
90
|
-
return {
|
|
91
|
-
backend: 'ie11',
|
|
92
|
-
available: ie11Available,
|
|
93
|
-
reason: ie11Available ? undefined : 'IE11 msCrypto not available'
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
case 'purejs':
|
|
97
|
-
return {
|
|
98
|
-
backend: 'purejs',
|
|
99
|
-
available: PureJSBackend.isAvailable(),
|
|
100
|
-
reason: 'Always available'
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
default:
|
|
104
|
-
return {
|
|
105
|
-
backend,
|
|
106
|
-
available: false,
|
|
107
|
-
reason: 'Unknown backend'
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
export async function getAllAvailableBackends(): Promise<string[]> {
|
|
113
|
-
const backends = ['webcrypto', 'nodecrypto', 'ie11', 'purejs'];
|
|
114
|
-
const available: string[] = [];
|
|
115
|
-
|
|
116
|
-
for (const backend of backends) {
|
|
117
|
-
const { available: isAvailable } = await checkBackendAvailability(backend);
|
|
118
|
-
if (isAvailable) {
|
|
119
|
-
available.push(backend);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
return available;
|
|
124
|
-
}
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
### 3. Rating backend'ов по приоритету
|
|
128
|
-
|
|
129
|
-
Создать файл `src/detection/backend-ranking.ts`:
|
|
130
|
-
|
|
131
|
-
```typescript
|
|
132
|
-
export interface BackendPriority {
|
|
133
|
-
name: string;
|
|
134
|
-
priority: number;
|
|
135
|
-
description: string;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
export const BACKEND_PRIORITY: BackendPriority[] = [
|
|
139
|
-
{
|
|
140
|
-
name: 'nodecrypto',
|
|
141
|
-
priority: 1,
|
|
142
|
-
description: 'Node.js native crypto (fastest)'
|
|
143
|
-
},
|
|
144
|
-
{
|
|
145
|
-
name: 'webcrypto',
|
|
146
|
-
priority: 2,
|
|
147
|
-
description: 'Web Crypto API (fast, hardware accelerated)'
|
|
148
|
-
},
|
|
149
|
-
{
|
|
150
|
-
name: 'ie11',
|
|
151
|
-
priority: 3,
|
|
152
|
-
description: 'IE11 msCrypto (legacy)'
|
|
153
|
-
},
|
|
154
|
-
{
|
|
155
|
-
name: 'purejs',
|
|
156
|
-
priority: 4,
|
|
157
|
-
description: 'Pure JavaScript (always available, slower)'
|
|
158
|
-
}
|
|
159
|
-
];
|
|
160
|
-
|
|
161
|
-
export function getBestAvailableBackend(availableBackends: string[]): string {
|
|
162
|
-
const sortedPriority = [...BACKEND_PRIORITY].sort((a, b) => a.priority - b.priority);
|
|
163
|
-
|
|
164
|
-
for (const { name } of sortedPriority) {
|
|
165
|
-
if (availableBackends.includes(name)) {
|
|
166
|
-
return name;
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
return 'purejs'; // Fallback
|
|
171
|
-
}
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
### 4. Integration с фабрикой адаптеров
|
|
175
|
-
|
|
176
|
-
В `src/detection/index.ts`:
|
|
177
|
-
|
|
178
|
-
```typescript
|
|
179
|
-
export { detectEnvironment, isNode, isBrowser, isWebWorker, RuntimeEnvironment } from './environment.js';
|
|
180
|
-
export { checkBackendAvailability, getAllAvailableBackends } from './backend-availability.js';
|
|
181
|
-
export { BACKEND_PRIORITY, getBestAvailableBackend } from './backend-ranking.js';
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
### 5. Tests
|
|
185
|
-
|
|
186
|
-
Создать файл `__tests__/detection/environment.test.ts`:
|
|
187
|
-
|
|
188
|
-
```typescript
|
|
189
|
-
describe('Environment Detection', () => {
|
|
190
|
-
it('should detect Node.js environment', () => {
|
|
191
|
-
const env = detectEnvironment();
|
|
192
|
-
expect(env).toBeDefined();
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
it('should detect browser environment', () => {
|
|
196
|
-
const isBrowser = detectEnvironment() === RuntimeEnvironment.BROWSER;
|
|
197
|
-
// May be true or false depending on test environment
|
|
198
|
-
expect(typeof isBrowser).toBe('boolean');
|
|
199
|
-
});
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
describe('Backend Availability', () => {
|
|
203
|
-
it('should check pure JS availability', async () => {
|
|
204
|
-
const result = await checkBackendAvailability('purejs');
|
|
205
|
-
expect(result.available).toBe(true);
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
it('should check web crypto availability', async () => {
|
|
209
|
-
const result = await checkBackendAvailability('webcrypto');
|
|
210
|
-
expect(typeof result.available).toBe('boolean');
|
|
211
|
-
});
|
|
212
|
-
|
|
213
|
-
it('should get all available backends', async () => {
|
|
214
|
-
const backends = await getAllAvailableBackends();
|
|
215
|
-
expect(Array.isArray(backends)).toBe(true);
|
|
216
|
-
expect(backends.length).toBeGreaterThan(0);
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
it('should get best available backend', async () => {
|
|
220
|
-
const available = await getAllAvailableBackends();
|
|
221
|
-
const best = getBestAvailableBackend(available);
|
|
222
|
-
expect(typeof best).toBe('string');
|
|
223
|
-
});
|
|
224
|
-
});
|
|
225
|
-
```
|
|
226
|
-
|
|
227
|
-
## Ожидаемый результат
|
|
228
|
-
|
|
229
|
-
- ✅ System обнаружения окружения реализована
|
|
230
|
-
- ✅ Checking доступности backend'ов работает корректно
|
|
231
|
-
- ✅ Rating backend'ов по приоритету настроен
|
|
232
|
-
- ✅ Tests проходят успешно
|
|
@@ -1,210 +0,0 @@
|
|
|
1
|
-
# Task 08: Optimal Backend Detection System Implementation
|
|
2
|
-
|
|
3
|
-
## Goal
|
|
4
|
-
|
|
5
|
-
Создать систему интеллектуального выбора оптимального backend'а на основе окружения и приоритетов.
|
|
6
|
-
|
|
7
|
-
## Implementation
|
|
8
|
-
|
|
9
|
-
### 1. Создать файл src/detection/backend-detector.ts
|
|
10
|
-
|
|
11
|
-
```typescript
|
|
12
|
-
import { detectEnvironment, RuntimeEnvironment } from './environment.js';
|
|
13
|
-
import { checkBackendAvailability, getAllAvailableBackends } from './backend-availability.js';
|
|
14
|
-
import { BACKEND_PRIORITY, getBestAvailableBackend } from './backend-ranking.js';
|
|
15
|
-
import { PureJSBackend } from '../adapters/pure-js.js';
|
|
16
|
-
import { WebCryptoBackend } from '../adapters/web-crypto.js';
|
|
17
|
-
import { NodeCryptoBackend } from '../adapters/node-crypto.js';
|
|
18
|
-
import { IE11Backend } from '../adapters/ie11.js';
|
|
19
|
-
|
|
20
|
-
export interface DetectionResult {
|
|
21
|
-
backend: string;
|
|
22
|
-
environment: RuntimeEnvironment;
|
|
23
|
-
availableBackends: string[];
|
|
24
|
-
selectedBy: string;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export class BackendDetector {
|
|
28
|
-
private static instance: BackendDetector;
|
|
29
|
-
|
|
30
|
-
private constructor() {}
|
|
31
|
-
|
|
32
|
-
static getInstance(): BackendDetector {
|
|
33
|
-
if (!BackendDetector.instance) {
|
|
34
|
-
BackendDetector.instance = new BackendDetector();
|
|
35
|
-
}
|
|
36
|
-
return BackendDetector.instance;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
async detect(): Promise<DetectionResult> {
|
|
40
|
-
const environment = detectEnvironment();
|
|
41
|
-
const availableBackends = await getAllAvailableBackends();
|
|
42
|
-
const selectedBackend = getBestAvailableBackend(availableBackends);
|
|
43
|
-
|
|
44
|
-
// Determine why this backend was selected
|
|
45
|
-
let selectedBy = 'priority';
|
|
46
|
-
if (availableBackends.length === 1) {
|
|
47
|
-
selectedBy = 'only_available';
|
|
48
|
-
} else if (selectedBackend === 'nodecrypto') {
|
|
49
|
-
selectedBy = 'fastest_available';
|
|
50
|
-
} else if (selectedBackend === 'webcrypto') {
|
|
51
|
-
selectedBy = 'fastest_available';
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return {
|
|
55
|
-
backend: selectedBackend,
|
|
56
|
-
environment,
|
|
57
|
-
availableBackends,
|
|
58
|
-
selectedBy
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
async createBackend(detectedBackend?: string): Promise<any> {
|
|
63
|
-
const { backend } = detectedBackend
|
|
64
|
-
? { backend: detectedBackend }
|
|
65
|
-
: await this.detect();
|
|
66
|
-
|
|
67
|
-
switch (backend) {
|
|
68
|
-
case 'nodecrypto':
|
|
69
|
-
return new NodeCryptoBackend();
|
|
70
|
-
case 'webcrypto':
|
|
71
|
-
return new WebCryptoBackend();
|
|
72
|
-
case 'ie11':
|
|
73
|
-
return new IE11Backend();
|
|
74
|
-
case 'purejs':
|
|
75
|
-
default:
|
|
76
|
-
return new PureJSBackend();
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
async createBackendByName(name: string): Promise<any> {
|
|
81
|
-
switch (name) {
|
|
82
|
-
case 'nodecrypto':
|
|
83
|
-
return new NodeCryptoBackend();
|
|
84
|
-
case 'webcrypto':
|
|
85
|
-
return new WebCryptoBackend();
|
|
86
|
-
case 'ie11':
|
|
87
|
-
return new IE11Backend();
|
|
88
|
-
case 'purejs':
|
|
89
|
-
default:
|
|
90
|
-
return new PureJSBackend();
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
export const detector = BackendDetector.getInstance();
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
### 2. Упрощенная функция для быстрого использования
|
|
99
|
-
|
|
100
|
-
Создать файл `src/detection/index.ts`:
|
|
101
|
-
|
|
102
|
-
```typescript
|
|
103
|
-
export { detectEnvironment, isNode, isBrowser, isWebWorker, RuntimeEnvironment } from './environment.js';
|
|
104
|
-
export { checkBackendAvailability, getAllAvailableBackends } from './backend-availability.js';
|
|
105
|
-
export { BACKEND_PRIORITY, getBestAvailableBackend } from './backend-ranking.js';
|
|
106
|
-
export { BackendDetector, detector } from './backend-detector.js';
|
|
107
|
-
|
|
108
|
-
// Quick access functions
|
|
109
|
-
export async function detectBackend(detectedBackend?: string): Promise<any> {
|
|
110
|
-
return detector.createBackend(detectedBackend);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
export async function getAvailableBackends(): Promise<string[]> {
|
|
114
|
-
return getAllAvailableBackends();
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
export function getBackendPriority(): string[] {
|
|
118
|
-
return BACKEND_PRIORITY.map(b => b.name);
|
|
119
|
-
}
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
### 3. Integration с основным API
|
|
123
|
-
|
|
124
|
-
В `src/index.ts`:
|
|
125
|
-
|
|
126
|
-
```typescript
|
|
127
|
-
import { detector } from './detection/backend-detector.js';
|
|
128
|
-
|
|
129
|
-
export async function md5(data: string, options?: { backend?: string }): Promise<string> {
|
|
130
|
-
const backend = options?.backend
|
|
131
|
-
? await detector.createBackendByName(options.backend)
|
|
132
|
-
: await detector.createBackend();
|
|
133
|
-
|
|
134
|
-
return backend.hash(data);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// Export backend factory
|
|
138
|
-
export { detector as backendDetector } from './detection/backend-detector.js';
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
### 4. Tests
|
|
142
|
-
|
|
143
|
-
Создать файл `__tests__/detection/backend-detector.test.ts`:
|
|
144
|
-
|
|
145
|
-
```typescript
|
|
146
|
-
describe('BackendDetector', () => {
|
|
147
|
-
let detector: BackendDetector;
|
|
148
|
-
|
|
149
|
-
beforeAll(() => {
|
|
150
|
-
detector = BackendDetector.getInstance();
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
it('should detect backend', async () => {
|
|
154
|
-
const result = await detector.detect();
|
|
155
|
-
expect(result).toBeDefined();
|
|
156
|
-
expect(result.backend).toBeDefined();
|
|
157
|
-
expect(result.environment).toBeDefined();
|
|
158
|
-
expect(result.availableBackends).toBeInstanceOf(Array);
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
it('should create backend by name', async () => {
|
|
162
|
-
const backend = await detector.createBackendByName('purejs');
|
|
163
|
-
expect(backend).toBeDefined();
|
|
164
|
-
expect(typeof backend.hash).toBe('function');
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
it('should create default backend', async () => {
|
|
168
|
-
const backend = await detector.createBackend();
|
|
169
|
-
expect(backend).toBeDefined();
|
|
170
|
-
expect(typeof backend.hash).toBe('function');
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
it('should cache singleton instance', () => {
|
|
174
|
-
const instance1 = BackendDetector.getInstance();
|
|
175
|
-
const instance2 = BackendDetector.getInstance();
|
|
176
|
-
expect(instance1).toBe(instance2);
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
it('should handle backend name override', async () => {
|
|
180
|
-
const backend = await detector.createBackendByName('purejs');
|
|
181
|
-
const result = backend.hash('test');
|
|
182
|
-
expect(result).toBeDefined();
|
|
183
|
-
});
|
|
184
|
-
});
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
### 5. Documentation API
|
|
188
|
-
|
|
189
|
-
Добавить JSDoc комментарии:
|
|
190
|
-
|
|
191
|
-
```typescript
|
|
192
|
-
/**
|
|
193
|
-
* Detects the optimal backend for MD5 computation
|
|
194
|
-
* @returns Promise<DetectionResult> Object containing detected backend info
|
|
195
|
-
*
|
|
196
|
-
* @example
|
|
197
|
-
* const result = await detector.detect();
|
|
198
|
-
* console.log(result.backend); // 'nodecrypto'
|
|
199
|
-
* console.log(result.environment); // 'node'
|
|
200
|
-
* console.log(result.availableBackends); // ['nodecrypto', 'purejs']
|
|
201
|
-
*/
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
## Ожидаемый результат
|
|
205
|
-
|
|
206
|
-
- ✅ BackendDetector реализован
|
|
207
|
-
- ✅ Intelligent выбор backend'а работает
|
|
208
|
-
- ✅ Tests проходят успешно
|
|
209
|
-
- ✅ Интегрирован в основной API
|
|
210
|
-
- ✅ Documentation создана
|