# pure-md5

**A lightweight, zero-dependency MD5 hashing library for Node.js and browsers.**

[![npm version](https://img.shields.io/npm/v/pure-md5.svg?style=flat&color=informational)](https://npmjs.org/package/pure-md5)
[![npm downloads](https://img.shields.io/npm/dw/pure-md5.svg?style=flat&color=blue)](https://npmjs.org/package/pure-md5)
[![Coverage Status](https://coveralls.io/repos/github/eustatos/pure-md5/badge.svg?branch=master)](https://coveralls.io/github/eustatos/pure-md5?branch=master)
[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)

---

## Install

```bash
npm install pure-md5
```

## Quick Start

```javascript
import { md5 } from 'pure-md5';

md5('hello'); // "5d41402abc4b2a76b9719d911017c592"
```

For the smallest possible bundle, import from the minimal entry:

```javascript
import { md5 } from 'pure-md5/md5'; // ~1.5 KB gzipped
```

## Streaming & File Hashing

```javascript
import { hashFile, createMD5Stream } from 'pure-md5/stream';

// Hash a file
const result = await hashFile('large-file.bin');
console.log(result.digest); // "abc123..."

// Stream API
import fs from 'fs';
const stream = createMD5Stream();
stream.on('md5', r => console.log('MD5:', r.digest));
fs.createReadStream('large-file.bin').pipe(stream);
```

## Binary Data

```javascript
import { md5Buffer } from 'pure-md5';

const data = new Uint8Array([0x00, 0xFF, 0x80]);
md5Buffer(data); // correct hash for raw bytes
```

---

## Features

- **Zero dependencies** — no external packages, ever
- **~1.5 KB gzipped** for `md5()` (tree-shakeable)
- **Streaming** — hash multi-GB files without loading into memory
- **TypeScript** — full type definitions included
- **Universal** — works in Node.js and browsers
- **Binary-safe** — correct hashes for non-UTF-8 byte data

---

## API

### `md5(message: string): string`

Compute MD5 hash of a string (UTF-8 encoded).

```javascript
import { md5 } from 'pure-md5';
md5('hello'); // "5d41402abc4b2a76b9719d911017c592"
```

### `md5Buffer(data: Uint8Array | ArrayBuffer): string`

Compute MD5 hash of binary data.

```javascript
import { md5Buffer } from 'pure-md5';
md5Buffer(new Uint8Array([104, 101, 108, 108, 111])); // "5d41402abc4b2a76b9719d911017c592"
```

### `md5Async(message: string): Promise<string>`

Async wrapper with automatic backend selection.

```javascript
import { md5Async } from 'pure-md5';
await md5Async('hello'); // "5d41402abc4b2a76b9719d911017c592"
```

### Streaming API (`pure-md5/stream`)

| Function | Description |
|----------|-------------|
| `hashFile(path, options?)` | Hash a file asynchronously with optional progress |
| `hashFileDigest(path)` | Hash a file, return digest only |
| `hashFileSync(path)` | Synchronous file hash (small files) |
| `verifyFile(path, expected)` | Verify file integrity |
| `createMD5Stream()` | Create a Node.js Transform stream |
| `pipeThroughMD5(source)` | Pipe a stream through MD5, get a promise |
| `fromStream(stream)` | Create stream + result promise pair |
| `createProgressTracker(total, cb)` | Progress callback helper |

```javascript
import { hashFile, createProgressTracker } from 'pure-md5/stream';

const result = await hashFile('video.mp4', {
  onProgress: createProgressTracker(fileSize, pct => console.log(`${pct}%`))
});
```

### WHATWG Streams (Browser)

```javascript
import { MD5ReadableStream, hashBlob } from 'pure-md5/stream';

// Hash a Blob
const digest = await hashBlob(fileBlob);

// Hash a ReadableStream
const result = await MD5ReadableStream.hash(readableStream);
```

### Backend Adapters

```javascript
import { NodeCryptoBackend, BrowserBackend, PureJSBackend } from 'pure-md5';

const backend = new NodeCryptoBackend();
await backend.hash('hello');
```

Use `pure-md5/detect` for backend detection and fallback utilities.

---

## Comparison

| Feature | pure-md5 | js-md5 | crypto-js | node-md5 | Node crypto |
|---------|----------|--------|-----------|----------|-------------|
| MD5 only size | ~1.5 KB¹ | ~3 KB | ~68 KB² | ~3 KB | N/A |
| Dependencies | 0 | 0 | 0 | 0 | 0 |
| Streaming | ✅ | ❌ | ❌ | ❌ | ✅ |
| Browser | ✅ | ✅ | ✅ | ❌ | ❌ |
| TypeScript | ✅ | ⚠️ | ❌ | ❌ | ❌ |
| Binary-safe | ✅ | ✅ | ✅ | ✅ | ✅ |
| Tree-shaking | ✅ | ❌ | ❌ | ❌ | N/A |

¹ With `import { md5 } from 'pure-md5/md5'`
² crypto-js is a monolithic bundle

---

## CDN

```html
<script type="module">
  import { md5 } from 'https://esm.sh/pure-md5';
  console.log(md5('hello'));
</script>
```

---

## Documentation

- [Streaming API](STREAM_API.md)
- [Streaming Examples](STREAM_EXAMPLES.md)
- [Migration Guide](MIGRATION_GUIDE_STREAMS.md)
- [Troubleshooting](STREAM_TROUBLESHOOTING.md)

---

## Contributing

See [Contributing Guide](CONTRIBUTING.md).

```bash
git clone https://github.com/eustatos/pure-md5.git
cd pure-md5
npm install
npm test
```

## License

MIT — see [LICENSE.md](LICENSE.md).
