{"id":18684944,"url":"https://github.com/tknf/read-files","last_synced_at":"2026-01-21T22:32:45.715Z","repository":{"id":176511239,"uuid":"658105985","full_name":"tknf/read-files","owner":"tknf","description":"Utility for async use of FileReader API on browser","archived":false,"fork":false,"pushed_at":"2025-06-17T14:20:13.000Z","size":281,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-11-30T14:09:11.417Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tknf.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-06-24T19:34:56.000Z","updated_at":"2025-06-19T01:47:25.000Z","dependencies_parsed_at":null,"dependency_job_id":"8e13bebf-8139-46ca-9a1b-8c7ffd29dd10","html_url":"https://github.com/tknf/read-files","commit_stats":null,"previous_names":["tknf/read-files"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/tknf/read-files","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tknf%2Fread-files","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tknf%2Fread-files/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tknf%2Fread-files/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tknf%2Fread-files/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tknf","download_url":"https://codeload.github.com/tknf/read-files/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tknf%2Fread-files/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28645549,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-21T21:29:11.980Z","status":"ssl_error","status_checked_at":"2026-01-21T21:24:31.872Z","response_time":86,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-07T10:19:49.613Z","updated_at":"2026-01-21T22:32:45.703Z","avatar_url":"https://github.com/tknf.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/tknf/read-files/main/docs/read-files.png\" alt=\"Snowflake Logo\" width=\"250\" height=\"auto\"\u003e\n  \u003ch1\u003e@tknf/read-files\u003c/h1\u003e\n  \u003cp\u003eModern, Promise-based utility for reading files in the browser using the FileReader API\u003c/p\u003e\n\u003c/div\u003e\n\n[![Github Workflow Status](https://img.shields.io/github/actions/workflow/status/tknf/read-files/ci.yaml?branch=main)](https://github.com/tknf/read-files/actions)\n[![Github](https://img.shields.io/github/license/tknf/read-files)](https://github.com/tknf/read-files/blob/main/LICENSE)\n[![npm](https://img.shields.io/npm/v/@tknf/read-files)](https://www.npmjs.com/package/@tknf/read-files)\n[![npm bundle size](https://img.shields.io/bundlephobia/min/@tknf/read-files)](https://bundlephobia.com/package/@tknf/read-files)\n[![npm bundle size](https://img.shields.io/bundlephobia/minzip/@tknf/read-files)](https://bundlephobia.com/package/@tknf/read-files)\n[![Github commit activity](https://img.shields.io/github/commit-activity/m/tknf/read-files)](https://github.com/tknf/read-files/pulse)\n[![GitHub last commit](https://img.shields.io/github/last-commit/tknf/read-files)](https://github.com/tknf/read-files/commits/main)\n[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/tknf/read-files)\n\n\u003cbr\u003e\n\n## ✨ Features\n\n- 🎯 **Promise-based API** - Clean async/await syntax\n- 🛡️ **Type Safety** - Full TypeScript support with comprehensive types\n- 🔒 **Error Handling** - Both throwing and safe (non-throwing) variants\n- 📱 **Multiple Formats** - Support for ArrayBuffer, text, binary string, and data URL\n- 🎚️ **Event Callbacks** - Optional progress and lifecycle event handlers\n- 🧪 **Well Tested** - 95%+ test coverage with comprehensive edge case testing\n- 📦 **Zero Dependencies** - Lightweight with no external dependencies\n- 🌐 **Browser Support** - Works in all modern browsers supporting FileReader API\n\n## 📦 Installation\n\n```bash\n# npm\nnpm install @tknf/read-files\n\n# yarn\nyarn add @tknf/read-files\n\n# pnpm\npnpm add @tknf/read-files\n```\n\n## 🚀 Quick Start\n\n### Basic Usage\n\n```typescript\nimport { readAsText, readAsArrayBuffer, readAsDataUrl } from '@tknf/read-files';\n\n// Read file as text\nconst file = new File(['Hello World'], 'hello.txt', { type: 'text/plain' });\nconst text = await readAsText(file);\nconsole.log(text); // \"Hello World\"\n\n// Read file as ArrayBuffer\nconst buffer = await readAsArrayBuffer(file);\nconsole.log(buffer.byteLength); // 11\n\n// Read file as data URL\nconst dataUrl = await readAsDataUrl(file);\nconsole.log(dataUrl); // \"data:text/plain;base64,SGVsbG8gV29ybGQ=\"\n```\n\n### Safe (Non-throwing) Variants\n\n```typescript\nimport { safeReadAsText, safeReadAsArrayBuffer } from '@tknf/read-files';\n\n// Safe reading - returns { result, error } instead of throwing\nconst { result, error } = await safeReadAsText(file);\n\nif (error) {\n  console.error('Failed to read file:', error.message);\n} else {\n  console.log('File content:', result);\n}\n```\n\n## 📚 API Reference\n\n### Reading Functions\n\n#### `readAsText(data, options?)`\nReads a File or Blob as text with optional character encoding.\n\n```typescript\nawait readAsText(file, { encoding: 'UTF-8' });\n```\n\n#### `readAsArrayBuffer(data, options?)`\nReads a File or Blob as an ArrayBuffer for binary data processing.\n\n```typescript\nawait readAsArrayBuffer(file);\n```\n\n#### `readAsBinaryString(data, options?)`\nReads a File or Blob as a binary string where each byte is represented as a character.\n\n```typescript\nawait readAsBinaryString(file);\n```\n\n#### `readAsDataUrl(data, options?)`\nReads a File or Blob as a data URL with embedded base64-encoded content.\n\n```typescript\nawait readAsDataUrl(file);\n```\n\n### Safe Variants\n\nAll reading functions have corresponding safe variants that return `{ result, error }` instead of throwing:\n\n- `safeReadAsText(data, options?)`\n- `safeReadAsArrayBuffer(data, options?)`\n- `safeReadAsBinaryString(data, options?)`\n- `safeReadAsDataUrl(data, options?)`\n\n### Options\n\n```typescript\ninterface ReadFilePromiseOptions\u003cResultType\u003e {\n  // Optional pre-configured FileReader instance\n  fileReader?: FileReader;\n  \n  // Event callbacks\n  onLoad?(event: ProgressEvent\u003cFileReader\u003e, result: ResultType): void;\n  onLoadStart?(event: ProgressEvent\u003cFileReader\u003e): void;\n  onLoadEnd?(event: ProgressEvent\u003cFileReader\u003e, result: ResultType): void;\n  onProgress?(event: ProgressEvent\u003cFileReader\u003e): void;\n  onError?(event: ProgressEvent\u003cFileReader\u003e, error: DOMException): void;\n}\n\n// Extended options for text reading\ninterface ReadAsTextOptions extends ReadFilePromiseOptions\u003cstring\u003e {\n  encoding?: string; // Character encoding (e.g., \"UTF-8\", \"ISO-8859-1\")\n}\n```\n\n### Utility Functions\n\n#### `isString(value)`\nType guard to check if a FileReader result is a string.\n\n```typescript\nimport { isString } from '@tknf/read-files';\n\nif (isString(result)) {\n  // result is definitely a string\n}\n```\n\n#### `isArrayBuffer(value)`\nType guard to check if a FileReader result is an ArrayBuffer.\n\n```typescript\nimport { isArrayBuffer } from '@tknf/read-files';\n\nif (isArrayBuffer(result)) {\n  // result is definitely an ArrayBuffer\n}\n```\n\n## 💡 Examples\n\n### File Upload with Progress\n\n```typescript\nimport { readAsDataUrl } from '@tknf/read-files';\n\nconst handleFileUpload = async (file: File) =\u003e {\n  try {\n    const dataUrl = await readAsDataUrl(file, {\n      onLoadStart: () =\u003e console.log('Reading started...'),\n      onProgress: (event) =\u003e {\n        if (event.lengthComputable) {\n          const progress = (event.loaded / event.total) * 100;\n          console.log(`Progress: ${progress.toFixed(2)}%`);\n        }\n      },\n      onLoadEnd: () =\u003e console.log('Reading completed'),\n    });\n    \n    // Use the data URL (e.g., for image preview)\n    const img = document.createElement('img');\n    img.src = dataUrl;\n    document.body.appendChild(img);\n  } catch (error) {\n    console.error('Failed to read file:', error);\n  }\n};\n```\n\n### Processing Binary Data\n\n```typescript\nimport { readAsArrayBuffer } from '@tknf/read-files';\n\nconst processBinaryFile = async (file: File) =\u003e {\n  const buffer = await readAsArrayBuffer(file);\n  const view = new DataView(buffer);\n  \n  // Read binary data\n  const signature = view.getUint32(0, true);\n  console.log('File signature:', signature.toString(16));\n  \n  // Process the binary data...\n};\n```\n\n### Error Handling with Safe Variants\n\n```typescript\nimport { safeReadAsText } from '@tknf/read-files';\n\nconst readFileContent = async (file: File) =\u003e {\n  const { result, error } = await safeReadAsText(file, {\n    encoding: 'UTF-8'\n  });\n  \n  if (error) {\n    if (error instanceof DOMException) {\n      console.error('FileReader error:', error.message);\n    } else {\n      console.error('Unexpected error:', error);\n    }\n    return null;\n  }\n  \n  return result;\n};\n```\n\n### Custom FileReader Configuration\n\n```typescript\nimport { readAsText } from '@tknf/read-files';\n\n// Use a pre-configured FileReader\nconst customReader = new FileReader();\nconst text = await readAsText(file, {\n  fileReader: customReader,\n  onError: (event, error) =\u003e {\n    console.error('Custom error handler:', error);\n  }\n});\n```\n\n## 🛠️ Development\n\n### Setup\n\n```bash\ngit clone https://github.com/tknf/read-files.git\ncd read-files\npnpm install\n```\n\n### Scripts\n\n```bash\n# Build the library\npnpm run build\n\n# Run tests\npnpm run test\n\n# Run tests with coverage\npnpm run test:coverage\n\n# Lint code\npnpm run lint\n\n# Format code\npnpm run format\n\n# Type check\npnpm run typecheck\n```\n\n### Project Structure\n\n```\nsrc/\n├── index.ts                   # Main exports\n├── types.ts                   # TypeScript type definitions\n├── utils.ts                   # Utility functions and type guards\n├── read-as-text.ts            # Text reading implementation\n├── read-as-array-buffer.ts    # ArrayBuffer reading implementation\n├── read-as-binary-string.ts   # Binary string reading implementation\n├── read-as-data-url.ts        # Data URL reading implementation\n└── **/*.test.ts               # Comprehensive test suites\n```\n\n## 🔧 Requirements\n\n- **Browser Environment**: Modern browsers with FileReader API support\n- **TypeScript**: 4.5+ (if using TypeScript)\n- **Node.js**: 16+ (for development)\n\n## 📄 License\n\nMIT License - see the [LICENSE](LICENSE) file for details.\n\n## 🤝 Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.\n\n### Development Guidelines\n\n1. **Code Style**: We use Biome for formatting and linting\n2. **Testing**: Maintain test coverage above 95%\n3. **TypeScript**: Ensure full type safety\n4. **Documentation**: Update README for any API changes\n\n## 🙏 Acknowledgments\n\n- Built with TypeScript and modern development tools\n- Tested with Vitest and comprehensive test scenarios\n- Formatted and linted with Biome\n- Bundled with tsup for optimal distribution\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftknf%2Fread-files","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftknf%2Fread-files","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftknf%2Fread-files/lists"}