{"_id":"@jsxx/bytes","_rev":"2-6b590ffd971afa3fce5ffa134a14bc00","name":"@jsxx/bytes","dist-tags":{"latest":"1.0.1"},"versions":{"1.0.0":{"name":"@jsxx/bytes","version":"1.0.0","keywords":["bytes","convert","parser","formatter","human-readable","file-size","storage","kb","mb","gb"],"author":{"name":"Aashish Panchal","email":"aipanchal51@gmail.com"},"license":"MIT","_id":"@jsxx/bytes@1.0.0","maintainers":[{"name":"aashishpanchal","email":"aipanchal51@gmail.com"}],"homepage":"https://github.com/vajra-labs/jsxx/blob/main/docs/bytes.md","bugs":{"url":"https://github.com/vajra-labs/jsxx/issues"},"dist":{"shasum":"3b4135a7b1a516de5fbc51c4c52017faf5f30be2","tarball":"https://registry.npmjs.org/@jsxx/bytes/-/bytes-1.0.0.tgz","fileCount":6,"integrity":"sha512-k2JSTDujyR4iXo1JbWgTOIAn0EMyE7xgl8JT2g5CHseTgF+xPic2MkqRVhZrUOiOB+OaSQnvnTlWD8jr1upwHQ==","signatures":[{"sig":"MEUCIQCl+3DpKTNpZDW0x8X4HI24a11gheS+XlydUF5y2QUGbwIgZ+Sa2Q9mrYM1DwBrn7jZnwzAxGY6Y6GDuRrxIWEXYEc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":12412},"main":"dist/index.cjs","type":"module","types":"dist/index.d.cts","module":"dist/index.mjs","engines":{"node":">=20"},"exports":{".":{"import":{"types":"./dist/index.d.mts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"gitHead":"5704ade49e738347ce5d5c70345d0cc4a2c72a4d","scripts":{"lint":"eslint \"src/**/*.ts\" --fix","test":"vitest run","build":"tsdown","release":"pnpm build && pnpm test && npm publish","test:watch":"vitest","check-types":"tsc --noEmit"},"_npmUser":{"name":"aashishpanchal","email":"aipanchal51@gmail.com"},"repository":{"url":"git+https://github.com/vajra-labs/jsxx.git","type":"git","directory":"pkgs/bytes"},"_npmVersion":"11.6.2","description":"A lightweight, type-safe utility for converting between bytes and human-readable strings","directories":{},"_nodeVersion":"24.11.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"catalog:","tsdown":"catalog:","vitest":"catalog:","@repo/ts":"workspace:*","typescript":"catalog:","@types/node":"catalog:","@repo/eslint":"workspace:*","@repo/vitest":"workspace:*"},"_npmOperationalInternal":{"tmp":"tmp/bytes_1.0.0_1770589560097_0.5971836927822829","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@jsxx/bytes","version":"1.0.1","type":"module","description":"A lightweight, type-safe utility for converting between bytes and human-readable strings","author":{"name":"Aashish Panchal","email":"aipanchal51@gmail.com"},"license":"MIT","publishConfig":{"access":"public"},"main":"dist/index.cjs","types":"dist/index.d.cts","module":"dist/index.mjs","scripts":{"build":"tsdown","lint":"eslint \"src/**/*.ts\" --fix","check-types":"tsc --noEmit","test":"vitest run","test:watch":"vitest","release":"pnpm build && pnpm test && npm publish"},"exports":{".":{"import":{"types":"./dist/index.d.mts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"devDependencies":{"@repo/eslint":"workspace:*","@repo/ts":"workspace:*","@repo/vitest":"workspace:*","@types/node":"catalog:","eslint":"catalog:","tsdown":"catalog:","typescript":"catalog:","vitest":"catalog:"},"keywords":["bytes","convert","parser","formatter","human-readable","file-size","storage","kb","mb","gb"],"bugs":{"url":"https://github.com/vajra-labs/jsxx/issues"},"homepage":"https://github.com/vajra-labs/jsxx/blob/main/docs/bytes.md","repository":{"type":"git","url":"git+https://github.com/vajra-labs/jsxx.git","directory":"pkgs/bytes"},"engines":{"node":">=20"},"gitHead":"25d601a058eb779a43c6742fce2532915718a668","_id":"@jsxx/bytes@1.0.1","_nodeVersion":"24.11.1","_npmVersion":"11.6.2","dist":{"integrity":"sha512-a2XTigNGYGRcJcKf4kS7u04WqT6xHkKqd66MADfxHFWi2k2xTdU9ImHKlIj7BNDwTQSHAq5IZ5+NIvYbx83rGQ==","shasum":"76c628387f6ba5e4cfb5600c95add9555a818ab4","tarball":"https://registry.npmjs.org/@jsxx/bytes/-/bytes-1.0.1.tgz","fileCount":7,"unpackedSize":25259,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCBXLOI4Oq5kSby6PkuAMV1+6IPCzC30LFtHVD6ZIX/gAIgfCPmz9lRZDePD7DIDJdcXT0lhPi/z7qJQUAxi69yFyE="}]},"_npmUser":{"name":"aashishpanchal","email":"aipanchal51@gmail.com"},"directories":{},"maintainers":[{"name":"aashishpanchal","email":"aipanchal51@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/bytes_1.0.1_1770591321102_0.4660382573432913"},"_hasShrinkwrap":false}},"time":{"created":"2026-02-08T22:25:59.968Z","modified":"2026-02-08T22:55:21.359Z","1.0.0":"2026-02-08T22:26:00.236Z","1.0.1":"2026-02-08T22:55:21.230Z"},"bugs":{"url":"https://github.com/vajra-labs/jsxx/issues"},"author":{"name":"Aashish Panchal","email":"aipanchal51@gmail.com"},"license":"MIT","homepage":"https://github.com/vajra-labs/jsxx/blob/main/docs/bytes.md","keywords":["bytes","convert","parser","formatter","human-readable","file-size","storage","kb","mb","gb"],"repository":{"type":"git","url":"git+https://github.com/vajra-labs/jsxx.git","directory":"pkgs/bytes"},"description":"A lightweight, type-safe utility for converting between bytes and human-readable strings","maintainers":[{"name":"aashishpanchal","email":"aipanchal51@gmail.com"}],"readme":"# @jsxx/bytes\n\n[![NPM Version](https://img.shields.io/npm/v/@jsxx/bytes.svg)](https://www.npmjs.com/package/@jsxx/bytes)\n[![License](https://img.shields.io/npm/l/@jsxx/bytes.svg)](https://github.com/vajra-labs/jsxx/blob/main/LICENSE)\n\nA lightweight, type-safe utility library for converting between bytes and human-readable strings.\n\n## Features\n\n- **Zero dependencies** - Minimal footprint\n- **Type-safe** - Full TypeScript support with template literal types\n- **Dual API** - Single function for both formatting and parsing\n- **Smart formatting** - Auto-hides unnecessary decimals\n- **Customizable** - Control precision and formatting\n- **Fast** - Optimized for performance\n- **Well-tested** - Comprehensive test coverage\n\n## Installation\n\n```bash\nnpm add @jsxx/bytes\n# or\npnpm add @jsxx/bytes\n# or\nyarn add @jsxx/bytes\n# or\nbun add @jsxx/bytes\n```\n\n## Quick Start\n\n```typescript\nimport bytes from '@jsxx/bytes';\n\n// Format bytes to human-readable string\nbytes(1024); // \"1KB\"\nbytes(1536); // \"1.5KB\"\nbytes(1048576); // \"1MB\"\n\n// Parse human-readable string to bytes\nbytes('1KB'); // 1024\nbytes('1.5MB'); // 1572864\nbytes('2GB'); // 2147483648\n```\n\n## API Reference\n\n### `bytes(value, options?)`\n\nMain function with overloaded signatures for bidirectional conversion.\n\n#### Signature 1: Format bytes to string\n\n```typescript\nfunction bytes(value: number, options?: FormatOptions): string;\n```\n\nConverts a numeric byte count into a human-readable string using binary units (1024-based).\n\n**Parameters:**\n\n- `value` (number): The number of bytes to format\n- `options` (FormatOptions): Optional formatting options\n\n**Returns:** `string` - Formatted string like `\"1.5KB\"` or `\"2MB\"`\n\n**Examples:**\n\n```typescript\nbytes(0); // \"0B\"\nbytes(500); // \"500B\"\nbytes(1024); // \"1KB\"\nbytes(1536); // \"1.5KB\"\nbytes(1048576); // \"1MB\"\nbytes(1073741824); // \"1GB\"\nbytes(-1024); // \"-1KB\"\n\n// With custom decimals\nbytes(1536, {decimals: 0}); // \"2KB\"\nbytes(1536, {decimals: 2}); // \"1.5KB\"\nbytes(1075, {decimals: 2}); // \"1.05KB\"\n\n// With separator\nbytes(1024, {separator: ' '}); // \"1 KB\"\nbytes(1536, {separator: ' '}); // \"1.5 KB\"\n\n// Combined options\nbytes(1536, {decimals: 2, separator: ' '}); // \"1.5 KB\"\n```\n\n**Edge Cases:**\n\n- Returns `\"0B\"` for `0`, `Infinity`, `-Infinity`, or `NaN`\n- Supports negative numbers: `-1024` → `\"-1KB\"`\n- Automatically hides unnecessary decimals: `1024` → `\"1KB\"` (not \"1.0KB\")\n- Maximum supported unit: `PB` (Petabyte)\n\n---\n\n#### Signature 2: Parse string to bytes\n\n```typescript\nfunction bytes(value: ByteString | string): number;\n```\n\nParses a human-readable byte string into a numeric byte count using binary units (1024-based).\n\n**Parameters:**\n\n- `value` (ByteString | string): A formatted byte string (e.g., `\"10MB\"`, `\"512KB\"`)\n\n**Returns:** `number` - The number of bytes\n\n**Examples:**\n\n```typescript\nbytes('1B'); // 1\nbytes('1KB'); // 1024\nbytes('1.5KB'); // 1536\nbytes('1MB'); // 1048576\nbytes('1GB'); // 1073741824\nbytes('1TB'); // 1099511627776\nbytes('1PB'); // 1125899906842624\n```\n\n**Case Handling:**\n\n```typescript\nbytes('1kb'); // 1024 (lowercase works)\nbytes('1KB'); // 1024 (uppercase works)\nbytes('1Kb'); // 1024 (mixed case works)\n```\n\n**Throws:**\n\n- Invalid format (e.g., `\"ABC\"`, `\"100\"` without unit, `\"KB\"` without number)\n\n**Returns NaN:**\n\n- Invalid decimal format: `\"1.2.3KB\"`, `\"..5MB\"` (matches regex but invalid number)\n\n---\n\n### `formatBytes(bytes, options?)`\n\nExplicit function to format bytes to a human-readable string.\n\n```typescript\nfunction formatBytes(bytes: number, options?: FormatOptions): string;\n```\n\n**Parameters:**\n\n- `bytes` (number): The number of bytes\n- `options` (FormatOptions): Optional formatting options\n\n**Returns:** `string`\n\n**Example:**\n\n```typescript\nimport {formatBytes} from '@jsxx/bytes';\n\nformatBytes(1024); // \"1KB\"\nformatBytes(1536); // \"1.5KB\"\nformatBytes(1048576); // \"1MB\"\nformatBytes(1536, {decimals: 0}); // \"2KB\"\nformatBytes(1024, {separator: ' '}); // \"1 KB\"\n```\n\n---\n\n### `parseBytes(value)`\n\nExplicit function to parse a byte string into a number.\n\n```typescript\nfunction parseBytes(value: ByteString | string): number;\n```\n\n**Parameters:**\n\n- `value` (ByteString | string): A formatted byte string\n\n**Returns:** `number`\n\n**Throws:** Error if the string format is invalid\n\n**Example:**\n\n```typescript\nimport {parseBytes} from '@jsxx/bytes';\n\nparseBytes('1KB'); // 1024\nparseBytes('1.5MB'); // 1572864\nparseBytes('2GB'); // 2147483648\n```\n\n---\n\n### Types\n\n#### `ByteUnit`\n\n```typescript\ntype ByteUnit = 'B' | 'KB' | 'MB' | 'GB' | 'TB' | 'PB';\n```\n\nSupported byte units (binary, 1024-based).\n\n#### `ByteString`\n\n```typescript\ntype ByteString = `${number}${ByteUnit}` | `${number}${Lowercase<ByteUnit>}`;\n```\n\nTemplate literal type for type-safe byte strings. Ensures compile-time checking for valid formats.\n\n**Valid formats:**\n\n- `\"1KB\"`, `\"1.5MB\"`, `\"2GB\"` (uppercase units)\n- `\"1kb\"`, `\"1.5mb\"`, `\"2gb\"` (lowercase units)\n\n**Invalid formats** (caught at compile-time):\n\n- `\"1 KB\"` (space not allowed in type, but works at runtime)\n- `\"KB\"` (number required)\n- `\"100\"` (unit required)\n\n#### `FormatOptions`\n\n```typescript\ninterface FormatOptions {\n  /**\n   * Number of decimal places to display.\n   * @default 1\n   */\n  decimals?: number;\n  /**\n   * Separator between number and unit.\n   * @default ''\n   */\n  separator?: string;\n}\n```\n\nOptions for customizing byte formatting.\n\n## Supported Units\n\nAll units use **binary** (base-1024) calculation:\n\n| Unit | Name     | Bytes                 | Calculation |\n| ---- | -------- | --------------------- | ----------- |\n| B    | Byte     | 1                     | 1           |\n| KB   | Kilobyte | 1,024                 | 1024¹       |\n| MB   | Megabyte | 1,048,576             | 1024²       |\n| GB   | Gigabyte | 1,073,741,824         | 1024³       |\n| TB   | Terabyte | 1,099,511,627,776     | 1024⁴       |\n| PB   | Petabyte | 1,125,899,906,842,624 | 1024⁵       |\n\n## Usage Examples\n\n### Basic Formatting\n\n```typescript\nimport bytes from '@jsxx/bytes';\n\nconsole.log(bytes(1024)); // \"1KB\"\nconsole.log(bytes(1536)); // \"1.5KB\"\nconsole.log(bytes(1048576)); // \"1MB\"\nconsole.log(bytes(5242880)); // \"5MB\"\nconsole.log(bytes(1073741824)); // \"1GB\"\n```\n\n### Basic Parsing\n\n```typescript\nimport bytes from '@jsxx/bytes';\n\nconsole.log(bytes('1KB')); // 1024\nconsole.log(bytes('1.5KB')); // 1536\nconsole.log(bytes('5MB')); // 5242880\nconsole.log(bytes('1GB')); // 1073741824\n```\n\n### File Size Display\n\n```typescript\nimport bytes from '@jsxx/bytes';\n\nfunction displayFileSize(fileSizeInBytes: number) {\n  return `File size: ${bytes(fileSizeInBytes)}`;\n}\n\ndisplayFileSize(2048); // \"File size: 2KB\"\ndisplayFileSize(5242880); // \"File size: 5MB\"\n```\n\n### Parsing User Input\n\n```typescript\nimport bytes from '@jsxx/bytes';\n\nfunction validateUploadSize(input: string, maxSize: string) {\n  const uploadBytes = bytes(input as ByteString);\n  const maxBytes = bytes(maxSize as ByteString);\n\n  return uploadBytes <= maxBytes;\n}\n\nvalidateUploadSize('5MB', '10MB'); // true\nvalidateUploadSize('15MB', '10MB'); // false\n```\n\n### Custom Precision\n\n```typescript\nimport bytes from '@jsxx/bytes';\n\n// Default: 1 decimal place (auto-hidden if zero)\nbytes(1024); // \"1KB\"\nbytes(1536); // \"1.5KB\"\n\n// No decimals (rounded)\nbytes(1536, {decimals: 0}); // \"2KB\"\nbytes(1700, {decimals: 0}); // \"2KB\"\n\n// 2 decimal places\nbytes(1075, {decimals: 2}); // \"1.05KB\"\nbytes(1100, {decimals: 2}); // \"1.07KB\"\n\n// 3 decimal places\nbytes(1075, {decimals: 3}); // \"1.05KB\"\nbytes(1100, {decimals: 3}); // \"1.074KB\"\n```\n\n### With Separators\n\n```typescript\nimport bytes from '@jsxx/bytes';\n\n// Space separator\nbytes(1024, {separator: ' '}); // \"1 KB\"\nbytes(1536, {separator: ' '}); // \"1.5 KB\"\n\n// Custom separators\nbytes(1024, {separator: '-'}); // \"1-KB\"\nbytes(1536, {separator: '_'}); // \"1.5_KB\"\n\n// Combined with decimals\nbytes(1536, {decimals: 2, separator: ' '}); // \"1.5 KB\"\nbytes(1024, {decimals: 0, separator: ' '}); // \"1 KB\"\n```\n\n### Memory Usage Monitoring\n\n```typescript\nimport bytes from '@jsxx/bytes';\n\nconst memoryUsage = process.memoryUsage();\n\nconsole.log('RSS:', bytes(memoryUsage.rss));\nconsole.log('Heap Total:', bytes(memoryUsage.heapTotal));\nconsole.log('Heap Used:', bytes(memoryUsage.heapUsed));\n```\n\n### Network Transfer Display\n\n```typescript\nimport bytes from '@jsxx/bytes';\n\nfunction showDownloadProgress(downloaded: number, total: number) {\n  return `${bytes(downloaded)} / ${bytes(total)}`;\n}\n\nshowDownloadProgress(524288, 1048576); // \"512KB / 1MB\"\n```\n\n### Configuration Parsing\n\n```typescript\nimport bytes from '@jsxx/bytes';\n\ninterface CacheConfig {\n  maxSize: string;\n}\n\nfunction getCacheMaxBytes(config: CacheConfig): number {\n  return bytes(config.maxSize as ByteString);\n}\n\ngetCacheMaxBytes({maxSize: '100MB'}); // 104857600\n```\n\n## Edge Cases & Behavior\n\n### Zero and Special Values\n\n```typescript\nbytes(0); // \"0B\"\nbytes(Infinity); // \"0B\"\nbytes(-Infinity); // \"0B\"\nbytes(NaN); // \"0B\"\n```\n\n### Negative Numbers\n\n```typescript\nbytes(-1024); // \"-1KB\"\nbytes(-1048576); // \"-1MB\"\n```\n\n### Smart Decimal Hiding\n\nThe library automatically hides unnecessary decimal places:\n\n```typescript\nbytes(1024); // \"1KB\" (not \"1.0KB\")\nbytes(2048); // \"2KB\" (not \"2.0KB\")\nbytes(1536); // \"1.5KB\" (keeps non-zero decimal)\nbytes(1075); // \"1.05KB\" (keeps necessary decimals)\n```\n\nYou can control this with the `decimals` option:\n\n```typescript\nbytes(1024, {decimals: 2}); // \"1KB\" (still hides if zero)\nbytes(1075, {decimals: 2}); // \"1.05KB\"\nbytes(1100, {decimals: 3}); // \"1.074KB\"\n```\n\n### Precision\n\nParsing uses `Math.floor()` for decimal results:\n\n```typescript\nbytes('1.5KB'); // 1536 (exactly 1.5 * 1024)\nbytes('1.999KB'); // 2046 (floor of 1.999 * 1024)\nbytes('0.5MB'); // 524288 (floor of 0.5 * 1048576)\n```\n\n### Invalid Input\n\n```typescript\n// Throws error\nparseBytes('invalid'); // Error: Invalid byte string: invalid\nparseBytes(''); // Error: Invalid byte string:\nparseBytes('100'); // Error: Invalid byte string: 100\nparseBytes('KB'); // Error: Invalid byte string: KB\n\n// Returns NaN (matches regex but invalid number)\nparseBytes('1.2.3KB'); // NaN\nparseBytes('..5MB'); // NaN\n```\n\n### Whitespace Handling\n\nRuntime whitespace is trimmed (though TypeScript type doesn't allow it):\n\n```typescript\nparseBytes(' 1KB ' as ByteString); // 1024 (works at runtime)\n```\n\n## TypeScript Usage\n\n### Type Safety\n\n```typescript\nimport bytes, {ByteString} from '@jsxx/bytes';\n\n// Valid at compile-time\nconst size: ByteString = '1.5MB';\nbytes(size); // ✓\n\n// Invalid at compile-time\nconst invalid: ByteString = '1 MB'; // ✗ Type error (but works at runtime)\nconst invalid2: ByteString = '100'; // ✗ Type error\n```\n\n### Function Overloads\n\nTypeScript correctly infers return types:\n\n```typescript\nconst str = bytes(1024); // type: string\nconst num = bytes('1KB'); // type: number\n```\n\n### Generic Usage\n\n```typescript\nfunction formatSize<T extends number | ByteString>(\n  value: T,\n): T extends number ? string : number {\n  return bytes(value as any);\n}\n\nformatSize(1024); // Returns string\nformatSize('1KB'); // Returns number\n```\n\n## Performance\n\n- **Lightweight**: ~1KB minified + gzipped\n- **Fast**: O(1) time complexity for both formatting and parsing\n- **Efficient**: Pre-computed unit mappings, minimal allocations\n- **No regex overhead**: Only one regex match per parse operation\n\n## Browser Support\n\nWorks in all modern browsers and Node.js environments that support:\n\n- ES2015+ features\n- `Number.isFinite()`\n- `Math.log()`, `Math.floor()`, `Math.pow()`\n- `String.prototype.trim()`, `String.prototype.match()`\n\n## Why @jsxx/bytes?\n\n### vs `bytes` (popular npm package)\n\n| Feature                | @jsxx/bytes | bytes   |\n| ---------------------- | ----------- | ------- |\n| Bundle size            | ~1KB        | ~2.5KB  |\n| TypeScript types       | ✓ Built-in  | ✓       |\n| Template literal types | ✓           | ✗       |\n| Auto-hide decimals     | ✓           | ✗       |\n| Custom decimals        | ✓           | ✓       |\n| Custom separator       | ✓           | ✗       |\n| Tree-shakeable         | ✓           | Limited |\n| ESM-first              | ✓           | ✗       |\n\n### Key Advantages\n\n- **Smaller bundle size** - 60% smaller than popular alternatives\n- **Better TypeScript support** - Template literal types for compile-time safety\n- **Smarter formatting** - Auto-hides unnecessary decimals\n- **Modern** - Written with modern JavaScript, ESM-first\n- **Well-tested** - Comprehensive test coverage including edge cases\n- **Part of @jsxx ecosystem** - Consistent API across @jsxx packages\n\n## Contributing\n\nContributions are welcome! Please ensure:\n\n1. All tests pass: `pnpm test`\n2. Code follows existing style: `pnpm lint`\n3. Types are correct: `pnpm check-types`\n4. Add tests for new features\n5. Update documentation\n\n## License\n\nMIT\n","readmeFilename":"README.md"}