{"id":15857453,"url":"https://github.com/TimMikeladze/use-fs","last_synced_at":"2025-09-20T10:32:24.681Z","repository":{"id":192988664,"uuid":"687190717","full_name":"TimMikeladze/use-fs","owner":"TimMikeladze","description":"🗂️ A React hook that enables you to read, write, and manage files directly - eliminating the need for repeated file selection dialogs. This capability is ideal for creating powerful browser-based tools.","archived":false,"fork":false,"pushed_at":"2025-07-25T17:40:43.000Z","size":2642,"stargazers_count":15,"open_issues_count":4,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-09-09T21:16:32.108Z","etag":null,"topics":["directory-changes","file-system","file-system-watcher","file-watcher","filesystem","fs","react","react-file-system","react-fs","use-fs","use-watch-directory","watch-directory"],"latest_commit_sha":null,"homepage":"https://use-fs.com","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/TimMikeladze.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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},"funding":{"ko_fi":"linesofcodedev","custom":["https://www.paypal.me/TimMikeladze"]}},"created_at":"2023-09-04T20:41:24.000Z","updated_at":"2025-08-28T11:46:27.000Z","dependencies_parsed_at":"2023-09-06T08:48:15.750Z","dependency_job_id":"82d4f957-c22d-4275-9185-098fffdaaf4b","html_url":"https://github.com/TimMikeladze/use-fs","commit_stats":null,"previous_names":["timmikeladze/use-file-system","timmikeladze/use-fs"],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/TimMikeladze/use-fs","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TimMikeladze%2Fuse-fs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TimMikeladze%2Fuse-fs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TimMikeladze%2Fuse-fs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TimMikeladze%2Fuse-fs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TimMikeladze","download_url":"https://codeload.github.com/TimMikeladze/use-fs/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TimMikeladze%2Fuse-fs/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274390550,"owners_count":25276406,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-09T02:00:10.223Z","response_time":80,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["directory-changes","file-system","file-system-watcher","file-watcher","filesystem","fs","react","react-file-system","react-fs","use-fs","use-watch-directory","watch-directory"],"created_at":"2024-10-05T20:23:13.971Z","updated_at":"2025-09-20T10:32:24.664Z","avatar_url":"https://github.com/TimMikeladze.png","language":"TypeScript","funding_links":["https://ko-fi.com/linesofcodedev","https://www.paypal.me/TimMikeladze"],"categories":[],"sub_categories":[],"readme":"# 🗂️ use-fs\n\nA React hook for integrating with the [File System Access API](https://developer.mozilla.org/en-US/docs/Web/API/File_System_Access_API). Visit [**use-fs.com**](https://use-fs.com) to try it out in your browser.\n\nThe File System Access API enables web applications to seamlessly work with files on a user's local system. After a user grants permission, web apps can read, write, and manage files directly - eliminating the need for repeated file selection dialogs. This capability is ideal for creating powerful browser-based tools.\n\nUnlike traditional file selection dialogs, the user will be prompted to select a directory, the hook will watch the files in that directory for changes - rerendering when changes are detected.\n\n\u003e ⚠️ Note: The File System API is not supported in all browsers. Works on Desktop in Chrome, Edge and Opera.\n\n## 📡 Install\n\n```console\nnpm install use-fs\n\nyarn add use-fs\n\npnpm add use-fs\n```\n\n\u003e 👋 Hello there! Follow me [@linesofcode](https://twitter.com/linesofcode) or visit [linesofcode.dev](https://linesofcode.dev) for more cool projects like this one.\n\n## 🚀 Getting Started\n\n```tsx\nimport { useFs } from \"use-fs\";\n\nfunction App() {\n  const { \n    onDirectorySelection, \n    files,\n    isBrowserSupported,\n    onClear,\n    isProcessing,\n    writeFile,\n    deleteFile,\n    startPolling,\n    stopPolling,\n    isPolling\n  } = useFs({\n    // Optional array of filter functions to exclude files/directories. By default `commonFilters` is used to ignore .git, node_modules, etc.\n    filters: [\n      // Built-in filters available:\n      // - distFilter (excludes dist/, build/, node_modules/, etc.)\n      // - gitFilter (respects .gitignore)\n      // - miscFilter (excludes .DS_Store, etc.)\n      // Or use commonFilters which includes all of the above\n    ],\n    \n    // Called when new files are added to the watched directory\n    onFilesAdded: (newFiles, previousFiles) =\u003e {\n      console.log('Files added:', newFiles);\n      // newFiles: Map\u003cstring, string\u003e - path -\u003e content\n      // previousFiles: Map\u003cstring, string\u003e - previous state\n    },\n\n    // Called when existing files are modified\n    onFilesChanged: (changedFiles, previousFiles) =\u003e {\n      console.log('Files changed:', changedFiles);\n      // changedFiles: Map\u003cstring, string\u003e - path -\u003e new content\n      // previousFiles: Map\u003cstring, string\u003e - previous state\n    },\n\n    // Called when files are deleted from the watched directory\n    onFilesDeleted: (deletedFiles, previousFiles) =\u003e {\n      console.log('Files deleted:', deletedFiles);\n      // deletedFiles: Map\u003cstring, string\u003e - path -\u003e last known content\n      // previousFiles: Map\u003cstring, string\u003e - previous state\n    },\n  });\n\n  if (!isBrowserSupported) {\n    return \u003cdiv\u003eBrowser not supported\u003c/div\u003e;\n  }\n\n  const handleSaveFile = async (path: string, content: string) =\u003e {\n    try {\n      await writeFile(path, content, { truncate: true });\n      console.log('File saved successfully');\n    } catch (error) {\n      console.error('Error saving file:', error);\n    }\n  };\n\n  const handleDeleteFile = async (path: string) =\u003e {\n    try {\n      await deleteFile(path);\n      console.log('File deleted successfully');\n    } catch (error) {\n      console.error('Error deleting file:', error);\n    }\n  };\n\n  return (\n    \u003cdiv\u003e\n      \u003cbutton \n        onClick={onDirectorySelection}\n        disabled={isProcessing}\n      \u003e\n        Select Directory\n      \u003c/button\u003e\n\n      \u003cbutton \n        onClick={onClear}\n        disabled={isProcessing}\n      \u003e\n        Clear\n      \u003c/button\u003e\n\n      \u003cbutton \n        onClick={startPolling}\n        disabled={isProcessing || isPolling}\n      \u003e\n        Start Polling\n      \u003c/button\u003e\n\n      \u003cbutton \n        onClick={stopPolling}\n        disabled={isProcessing || !isPolling}\n      \u003e\n        Stop Polling\n      \u003c/button\u003e\n\n      \u003cdiv\u003e\n        Status: {isPolling ? 'Polling Active' : 'Polling Stopped'}\n      \u003c/div\u003e\n\n      {files.size \u003e 0 \u0026\u0026 (\n        \u003cdiv\u003e\n          \u003ch2\u003eFiles ({files.size}):\u003c/h2\u003e\n          \u003cdiv\u003e\n            {Array.from(files.entries()).map(([path, content]) =\u003e (\n              \u003cdiv key={path}\u003e\n                \u003ch3\u003e{path}\u003c/h3\u003e\n                \u003cpre\u003e{content}\u003c/pre\u003e\n                \u003cbutton onClick={() =\u003e handleSaveFile(path, 'New content')}\u003e\n                  Save Changes\n                \u003c/button\u003e\n                \u003cbutton onClick={() =\u003e handleDeleteFile(path)}\u003e\n                  Delete File\n                \u003c/button\u003e\n              \u003c/div\u003e\n            ))}\n          \u003c/div\u003e\n        \u003c/div\u003e\n      )}\n    \u003c/div\u003e\n  );\n}\n```\n\nThe hook provides several key features:\n\n1. **File System Access**: Prompts users to select a directory and maintains access to it.\n2. **File Writing**: Allows writing content to files with options for truncation and creation.\n3. **File Deletion**: Enables safe removal of files from the selected directory.\n4. **File Watching**: Continuously monitors selected directory for changes with automatic polling.\n5. **Polling Control**: Manual control over when to start/stop monitoring for file changes.\n6. **Content Management**: Provides access to file contents and updates in real-time.\n7. **Filtering**: Built-in and custom filters to exclude unwanted files/directories.\n8. **Performance Optimizations**: \n   - Batched file processing\n   - Content caching\n   - Debounced updates\n   - Efficient change detection\n\n### Props\n\n- `filters?: FilterFn[]` - Array of filter functions to exclude files/directories\n- `onFilesAdded?: (newFiles: Map\u003cstring, string\u003e, previousFiles: Map\u003cstring, string\u003e) =\u003e void` - Callback when files are added\n- `onFilesChanged?: (changedFiles: Map\u003cstring, string\u003e, previousFiles: Map\u003cstring, string\u003e) =\u003e void` - Callback when files change\n- `onFilesDeleted?: (deletedFiles: Map\u003cstring, string\u003e, previousFiles: Map\u003cstring, string\u003e) =\u003e void` - Callback when files are deleted\n- `pollInterval?: number` - How often to check for changes (default: 100ms)\n- `batchSize?: number` - How many files to process in parallel (default: 50)\n- `debounceInterval?: number` - Debounce interval for updates (default: 50ms)\n- `fileCacheTtl?: number` - How long to cache file contents (default: 5000ms)\n\n### Return Values\n\n- `onDirectorySelection: () =\u003e Promise\u003cvoid\u003e` - Function to open directory picker\n- `onClear: () =\u003e void` - Function to stop watching and clear state\n- `files: Map\u003cstring, string\u003e` - Current map of file paths to contents\n- `isProcessing: boolean` - Whether files are being processed\n- `isBrowserSupported: boolean` - Whether File System API is supported\n- `writeFile: (path: string, data: string | ArrayBuffer | Blob, options?: FileWriteOptions) =\u003e Promise\u003cvoid\u003e` - Function to write to files\n- `deleteFile: (path: string) =\u003e Promise\u003cvoid\u003e` - Function to delete files\n- `startPolling: () =\u003e void` - Function to manually start polling for file changes\n- `stopPolling: () =\u003e void` - Function to manually stop polling for file changes  \n- `isPolling: boolean` - Whether the hook is actively polling for changes\n\n\n## 📚 Contributing\n\n1. Navigate to the `docs` directory\n2. Run `pnpm install` to install the dependencies\n3. Run `pnpm dev` to start the development server\n3. Navigate to `http://localhost:3000` to view the demo.\n5. Modify the `Demo.tsx` file to make your changes.\n\nIf you're making changes to the `use-fs` package, you can run `pnpm build` to build the package and then run `pnpm link use-fs` to link the package to the `docs` directory for local development and testing.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FTimMikeladze%2Fuse-fs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FTimMikeladze%2Fuse-fs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FTimMikeladze%2Fuse-fs/lists"}