{"_id":"@ashish-um/nook-files","name":"@ashish-um/nook-files","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"@ashish-um/nook-files","version":"1.0.0","description":"Binary file storage in Google Drive — companion to @ashish-um/nook","type":"module","main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"import":"./dist/index.js","require":"./dist/index.cjs"}},"scripts":{"build":"tsup","test":"vitest"},"keywords":["google-drive","storage","binary","files","upload","appdata"],"author":{"name":"ashish-um"},"license":"MIT","publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/ashish-um/nook-files.git"},"devDependencies":{"@types/node":"^25.5.2","dotenv":"^17.4.0","tsup":"^8.5.1","tsx":"^4.21.0","typescript":"^6.0.2","vitest":"^4.1.2","xhr2":"^0.2.1"},"gitHead":"0388e57e4046d92e7069c7142d6430f95f74de81","_id":"@ashish-um/nook-files@1.0.0","bugs":{"url":"https://github.com/ashish-um/nook-files/issues"},"homepage":"https://github.com/ashish-um/nook-files#readme","_nodeVersion":"25.8.1","_npmVersion":"11.12.0","dist":{"integrity":"sha512-My/BCkwYC9I11yuPlLjoqzRHLKxSX0kDrrYrd0bmv5doZwDpwzHOFNYDGE70E6erCZ6spuT/6VcTkxtY/aHurQ==","shasum":"f4e63cace36ef19d82af7b11aa830bc65f560f54","tarball":"https://registry.npmjs.org/@ashish-um/nook-files/-/nook-files-1.0.0.tgz","fileCount":8,"unpackedSize":33795,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQD6odG6HMbgYPgSI47FLzon4ap3BQtKdALUaw6sQHY59wIhAO+aW7btQaO0xxWHWoSCJ7N9oLxlb1uc8SvhwAd5nz1l"}]},"_npmUser":{"name":"ashish-um","email":"ashishumrao12345@gmail.com"},"directories":{},"maintainers":[{"name":"ashish-um","email":"ashishumrao12345@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/nook-files_1.0.0_1775471880835_0.0017620209944551046"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-06T10:38:00.736Z","1.0.0":"2026-04-06T10:38:00.982Z","modified":"2026-04-06T10:38:01.168Z"},"maintainers":[{"name":"ashish-um","email":"ashishumrao12345@gmail.com"}],"description":"Binary file storage in Google Drive — companion to @ashish-um/nook","homepage":"https://github.com/ashish-um/nook-files#readme","keywords":["google-drive","storage","binary","files","upload","appdata"],"repository":{"type":"git","url":"git+https://github.com/ashish-um/nook-files.git"},"author":{"name":"ashish-um"},"bugs":{"url":"https://github.com/ashish-um/nook-files/issues"},"license":"MIT","readme":"# nook-files\n\n> A companion package to `nook` for storing binary files (images, audio, video) in Google Drive's `appDataFolder`.\n\n## 📚 Documentation\n\n- [Official Documentation](./nook-files-documentation.md) — Comprehensive API reference, configuration options, and advanced examples.\n- [React & Next.js Guide](./react-nextjs-guide.md) — Beginner-friendly guide on handling OAuth implicit flows, `\"use client\"`, memory leak prevention, and building UI uploaders.\n\nWhile `@ashish-um/nook` is perfect for JSON storage, `nook-files` is designed specifically for raw binary data. It uses the same authentication pattern and same `appDataFolder` isolation, but preserves binary integrity and supports granular upload progress tracking for large files.\n\n## Installation\n\n```bash\nnpm install @ashish-um/nook-files\n```\n\n## Quick Start\n```typescript\nimport { DriveFiles } from \"@ashish-um/nook-files\";\n\n// Initialize with a Google OAuth2 access token\nconst files = new DriveFiles(accessToken);\n\n// Upload a binary file (e.g., from an <input type=\"file\">)\nconst imageFile = inputElement.files[0];\nconst entry = await files.create(\"notes/note-123/image-1.png\", imageFile, {\n  onProgress: (progress) => {\n    console.log(`Upload progress: ${progress.percent}%`);\n  }\n});\n\n// Download a binary file as a Blob\nconst blob = await files.read(\"notes/note-123/image-1.png\");\n\n// Display it in the browser\nconst url = URL.createObjectURL(blob);\ndocument.querySelector(\"img\").src = url;\n\n// Update the file content\nawait files.update(\"notes/note-123/image-1.png\", newBlob);\n\n// List files under a prefix path\nconst attachments = await files.list(\"notes/note-123/\");\n\n// Delete the file\nawait files.delete(\"notes/note-123/image-1.png\");\n```\n\n## Using with `nook`\n\n`nook-files` uses the exact same `DriveCRUDOptions` and token refresh callback structure as `nook`. You can initialize both side-by-side using the same token:\n\n```typescript\nimport { DriveCRUD } from \"@ashish-um/nook\";\nimport { DriveFiles } from \"@ashish-um/nook-files\";\n\nconst options = {\n  // Silent token refresh function used by both libraries\n  onTokenExpired: async () => await refreshMyAuthToken()\n};\n\nconst drive = new DriveCRUD(accessToken, options);\nconst files = new DriveFiles(accessToken, options);\n```\n\n### Storing Binary Attachments\n\nThe recommended pattern is to store the binary file through `nook-files` **first**, and then store the string reference to its path inside your JSON data through `nook`. \n\n```typescript\n// 1. Upload the image first\nconst entry = await files.create(`notes/note-123/avatar.png`, imageBlob);\n\n// 2. Save the metadata as a JSON record\nawait drive.create(`notes/note-123.json`, {\n  title: \"My Note\",\n  body: \"Some text\",\n  attachments: [\n    { name: entry.name, mimeType: entry.mimeType }\n  ]\n});\n```\n\n*Note: Drive API metadata uses a string for file sizes due to Javascript integer limits on very large files.*\n\n## Advanced: Resumable vs Multipart Uploads\n\n`DriveFiles` automatically chooses the most efficient upload strategy for you based on the blob size:\n1. **Multipart Upload**: Single XHR request. Used for files `< 5MB`.\n2. **Resumable Upload**: Initial session chunked via iterative PUT requests via XHR. Used for files `>= 5MB`.\n\nYou can configure this automatic threshold using options:\n```typescript\nconst files = new DriveFiles(accessToken, {\n  resumableThreshold: 10_000_000 // Switch to resumable at 10MB instead\n})\n```\n\n## Error Handling\n\nAll methods throw a `DriveFilesError` with strongly-typed fallback codes:\n\n```typescript\ntry {\n  await files.read(\"missing.png\");\n} catch (error) {\n  if (error.code === \"NOT_FOUND\") {\n    console.log(\"File is missing!\");\n  } else if (error.code === \"AUTH_ERROR\") {\n    console.log(\"Token expired and no onTokenExpired callback was provided.\");\n  }\n}\n```\n\n## License\nMIT\n","readmeFilename":"README.md","_rev":"1-023e66f354774dde9a18782fa123d45a"}