Security - Fix path traversal in GET /api/archives/:name/files. Express decodes route params after segment matching, so `..%2f..%2fetc` escaped ARCHIVES_DIR and returned a recursive listing of arbitrary directories. - Add CSP and baseline security headers; disable x-powered-by. - Stop baking GEMINI_API_KEY into the client bundle (the SDK was unused). - Run the container as `node` instead of root. Performance - Add a directory-mtime-keyed archive index, warmed in the background and persisted. Listing 110k files went from ~52s to ~0.1s; the largest archive (24k files) serves in ~0.3s. Per-file stat over CIFS costs ~1.4ms and does not parallelise, so it is now done once rather than per request. - Build media URLs from the File directly instead of `new Blob([await file.arrayBuffer()])`, which read every media file fully into memory (a 20GB archive tried to become 20GB of resident blobs). - Track and revoke object URLs; previously none were ever revoked. - Give `requestThumbnail` a stable identity so a completed thumbnail stops re-running the effect in every mounted thumbnail. - Namespace IndexedDB keys so listing archives no longer deserializes every cached thumbnail blob, and thumbnails no longer collide across archives. - Serve real file sizes: RemoteArchiveFile was constructed with size 0, which silently disabled high-res thumbnailing for every server archive. Correctness - Local archives cached media as blob: URLs, which die with the document, so a cached local archive restored as an archive of broken images. Media now carries a stable path and is rehydrated from a persisted directory handle (File System Access API), falling back to re-prompting for the folder. - Fix permalinks: the URL-writing effect erased ?a= on mount before the archive list arrived to consume it, so deep links never resolved. - Make cache invalidation detect nested changes via a directory signature. - Add an error boundary and tolerate unparseable dates, which previously threw a RangeError and blanked the app. - Default video to muted so autoplay is not blocked by Safari/Firefox. Features - Fold sidecar directories into their base profile: `<user> - reels`, `story - <user>` and `story highlights - <user> - <title>` now appear as reels, the story ring and Instagram-style highlight circles rather than as separate archives. Housekeeping - Add @types/react; React was previously type-checked against its JavaScript source, so `npm run lint` gave almost no type safety on components. - Vendor fonts and PWA icons locally; the app made third-party CDN requests despite advertising offline support and local-only processing. - Drop unused better-sqlite3 (a native module that broke `npm install`). - Add vitest with 36 tests over the filename and directory-naming rules. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011uBWhwV3wFQ5MBCcMHHem7
47 lines
1.3 KiB
JSON
47 lines
1.3 KiB
JSON
{
|
|
"name": "instaarchive-viewer",
|
|
"private": true,
|
|
"version": "1.2.0",
|
|
"type": "module",
|
|
"scripts": {
|
|
"dev": "vite --port=3000 --host=0.0.0.0",
|
|
"build": "vite build && npm run build:server",
|
|
"build:server": "tsc server.ts --esModuleInterop --module ESNext --target ES2022 --moduleResolution bundler --outDir dist-server",
|
|
"preview": "vite preview",
|
|
"server": "tsx server.ts",
|
|
"clean": "rm -rf dist",
|
|
"lint": "tsc --noEmit",
|
|
"test": "vitest run",
|
|
"test:watch": "vitest"
|
|
},
|
|
"dependencies": {
|
|
"@tailwindcss/vite": "^4.1.14",
|
|
"@vitejs/plugin-react": "^5.0.4",
|
|
"clsx": "^2.1.1",
|
|
"date-fns": "^4.1.0",
|
|
"dotenv": "^17.2.3",
|
|
"express": "^4.21.2",
|
|
"idb-keyval": "^6.2.2",
|
|
"lucide-react": "^0.546.0",
|
|
"motion": "^12.23.24",
|
|
"react": "^19.0.0",
|
|
"react-dom": "^19.0.0",
|
|
"tailwind-merge": "^3.5.0",
|
|
"tsx": "^4.21.0",
|
|
"vite": "^6.2.0",
|
|
"xz-decompress": "^0.2.3"
|
|
},
|
|
"devDependencies": {
|
|
"@types/express": "^4.17.21",
|
|
"@types/node": "^22.14.0",
|
|
"@types/react": "^19.2.18",
|
|
"@types/react-dom": "^19.2.4",
|
|
"autoprefixer": "^10.4.21",
|
|
"tailwindcss": "^4.1.14",
|
|
"typescript": "~5.8.2",
|
|
"vite": "^6.2.0",
|
|
"vite-plugin-pwa": "^1.2.0",
|
|
"vitest": "^3.2.7"
|
|
}
|
|
}
|