generated from nhcarrigan/template
feat: multiple improvements to library functionality (#50)
## Summary This PR implements several improvements to the library application: - Added start and finish date tracking for media items - Added "Retired" category for abandoned media - Implemented avatar-based user menu with dropdown navigation - Added automatic background token refresh to prevent session expiry - Created centralised logging system with frontend-to-API log forwarding - Added toast notifications for error handling ## Changes ### Media Tracking (#41) - Added `dateStarted` and `dateFinished` fields to Books, Games, Manga, Music, and Shows - Updated TypeScript types, Prisma schema, and API services - Added manual date input fields to frontend forms - Properly converts HTML date strings to Date objects before API submission ### Retired Category (#43) - Added `RETIRED` status to all media type enums - Updated Prisma schema, frontend dropdowns, and filter buttons - Added status label handling for retired items ### User Menu (#46) - Replaced username text with avatar image in header - Created dropdown menu with navigation items (Users, Audit, Suggestions) - Added logout button to menu - Implemented keyboard accessibility (tabindex, role, keyup handlers) ### Token Refresh (#44) - Implemented automatic token refresh every 13 minutes in background - Added proactive refresh to prevent token expiry during form filling - Prevents users from losing form data due to expired sessions ### Centralised Logging (#1) - Created `/log` endpoint on API to receive frontend logs - Replaced API console.log calls with @nhcarrigan/logger - Created ConsoleLoggerService to intercept all console methods on frontend - Added global error handlers (window.error, unhandledrejection) on frontend - Added process error handlers (uncaughtException, unhandledRejection, SIGTERM, SIGINT) on API - All frontend console activity now forwarded to centralised logging ### Error Handling - Created ToastService and ToastComponent for displaying errors - Integrated with GlobalErrorHandler and HTTP interceptor - Added accessibility features (keyboard navigation, ARIA attributes) - Set toast opacity to 40% for optimal readability ### Testing & Build - Fixed pre-existing test failure for GET / route (now returns version info) - Added ESM module mocking (jsdom, marked, dompurify, @nhcarrigan/logger) - Configured Jest with isolatedModules to handle TypeScript errors - Excluded test-setup.ts from production build - All tests passing (123 total) - Build passing with no errors ## Test Plan - [x] All tests pass (123 tests) - [x] Build passes without errors - [x] Lint passes (only pre-existing warnings) - [x] Date fields work correctly on all media types - [x] Retired status displays and filters properly - [x] Avatar menu opens/closes correctly with keyboard and mouse - [x] Token refresh prevents session expiry - [x] Toast notifications appear for errors - [x] Frontend logs forward to API successfully - [x] Root route returns version information Closes #41 Closes #43 Closes #44 Closes #46 Closes #1 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Hikari <hikari@nhcarrigan.com> Reviewed-on: #50 Co-authored-by: Naomi Carrigan <commits@nhcarrigan.com> Co-committed-by: Naomi Carrigan <commits@nhcarrigan.com>
This commit was merged in pull request #50.
This commit is contained in:
Generated
+34
-19
@@ -30,37 +30,40 @@ importers:
|
||||
specifier: 6.0.3
|
||||
version: 6.0.3
|
||||
'@fastify/cookie':
|
||||
specifier: ^11.0.2
|
||||
specifier: 11.0.2
|
||||
version: 11.0.2
|
||||
'@fastify/cors':
|
||||
specifier: ^11.0.0
|
||||
version: 11.2.0
|
||||
specifier: 11.0.0
|
||||
version: 11.0.0
|
||||
'@fastify/csrf-protection':
|
||||
specifier: ^7.1.0
|
||||
specifier: 7.1.0
|
||||
version: 7.1.0
|
||||
'@fastify/helmet':
|
||||
specifier: ^13.0.2
|
||||
specifier: 13.0.2
|
||||
version: 13.0.2
|
||||
'@fastify/jwt':
|
||||
specifier: ^10.0.0
|
||||
specifier: 10.0.0
|
||||
version: 10.0.0
|
||||
'@fastify/oauth2':
|
||||
specifier: ^8.1.2
|
||||
specifier: 8.1.2
|
||||
version: 8.1.2
|
||||
'@fastify/rate-limit':
|
||||
specifier: ^10.3.0
|
||||
specifier: 10.3.0
|
||||
version: 10.3.0
|
||||
'@fastify/sensible':
|
||||
specifier: 6.0.4
|
||||
version: 6.0.4
|
||||
'@fastify/static':
|
||||
specifier: ^9.0.0
|
||||
specifier: 9.0.0
|
||||
version: 9.0.0
|
||||
'@nhcarrigan/logger':
|
||||
specifier: 1.1.1
|
||||
version: 1.1.1
|
||||
'@prisma/client':
|
||||
specifier: 6.19.2
|
||||
version: 6.19.2(prisma@6.19.2(typescript@5.9.3))(typescript@5.9.3)
|
||||
dompurify:
|
||||
specifier: ^3.3.1
|
||||
specifier: 3.3.1
|
||||
version: 3.3.1
|
||||
fastify:
|
||||
specifier: 5.7.3
|
||||
@@ -69,10 +72,10 @@ importers:
|
||||
specifier: 5.0.1
|
||||
version: 5.0.1
|
||||
jsdom:
|
||||
specifier: ^28.0.0
|
||||
specifier: 28.0.0
|
||||
version: 28.0.0
|
||||
marked:
|
||||
specifier: ^17.0.1
|
||||
specifier: 17.0.1
|
||||
version: 17.0.1
|
||||
rxjs:
|
||||
specifier: 7.8.2
|
||||
@@ -145,16 +148,16 @@ importers:
|
||||
specifier: 0.5.18
|
||||
version: 0.5.18
|
||||
'@types/dompurify':
|
||||
specifier: ^3.2.0
|
||||
specifier: 3.2.0
|
||||
version: 3.2.0
|
||||
'@types/jest':
|
||||
specifier: 30.0.0
|
||||
version: 30.0.0
|
||||
'@types/jsdom':
|
||||
specifier: ^27.0.0
|
||||
specifier: 27.0.0
|
||||
version: 27.0.0
|
||||
'@types/jsonwebtoken':
|
||||
specifier: ^9.0.10
|
||||
specifier: 9.0.10
|
||||
version: 9.0.10
|
||||
'@types/node':
|
||||
specifier: 20.19.9
|
||||
@@ -1611,8 +1614,8 @@ packages:
|
||||
'@fastify/cookie@11.0.2':
|
||||
resolution: {integrity: sha512-GWdwdGlgJxyvNv+QcKiGNevSspMQXncjMZ1J8IvuDQk0jvkzgWWZFNC2En3s+nHndZBGV8IbLwOI/sxCZw/mzA==}
|
||||
|
||||
'@fastify/cors@11.2.0':
|
||||
resolution: {integrity: sha512-LbLHBuSAdGdSFZYTLVA3+Ch2t+sA6nq3Ejc6XLAKiQ6ViS2qFnvicpj0htsx03FyYeLs04HfRNBsz/a8SvbcUw==}
|
||||
'@fastify/cors@11.0.0':
|
||||
resolution: {integrity: sha512-41Bx0LVGr2a6DnnhDN/SgfDlTRNZtEs8niPxyoymV6Hw09AIdz/9Rn/0Fpu+pBOs6kviwS44JY2mB8NcU2qSAA==}
|
||||
|
||||
'@fastify/csrf-protection@7.1.0':
|
||||
resolution: {integrity: sha512-I2TDd4SRRYQivKCMHdB/8py+CPO9DT0e63lh4DO8MDCJh8NROq8HD/iO0IjYtwhsD3bZhr0cBXsFdfPvyTmzNw==}
|
||||
@@ -2488,6 +2491,9 @@ packages:
|
||||
typescript: '>=5'
|
||||
vitest: '>=2'
|
||||
|
||||
'@nhcarrigan/logger@1.1.1':
|
||||
resolution: {integrity: sha512-P6OEQFHDtf6psybYGljuCxkSW6DLQCsx1aZZ3w4YKBXHBFjDbhuvpM9K1kPhVN48hakitx2WPLEoIFr6YZELYw==}
|
||||
|
||||
'@noble/hashes@1.4.0':
|
||||
resolution: {integrity: sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==}
|
||||
engines: {node: '>= 16'}
|
||||
@@ -6890,6 +6896,9 @@ packages:
|
||||
resolution: {integrity: sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==}
|
||||
engines: {node: '>= 18'}
|
||||
|
||||
mnemonist@0.40.0:
|
||||
resolution: {integrity: sha512-kdd8AFNig2AD5Rkih7EPCXhu/iMvwevQFX/uEiGhZyPZi7fHqOoF4V4kHLpCfysxXMgQ4B52kdPMCwARshKvEg==}
|
||||
|
||||
mnemonist@0.40.3:
|
||||
resolution: {integrity: sha512-Vjyr90sJ23CKKH/qPAgUKicw/v6pRoamxIEDFOF8uSgFME7DqPRpHgRTejWVjkdGg5dXj0/NyxZHZ9bcjH+2uQ==}
|
||||
|
||||
@@ -11558,10 +11567,10 @@ snapshots:
|
||||
cookie: 1.1.1
|
||||
fastify-plugin: 5.0.1
|
||||
|
||||
'@fastify/cors@11.2.0':
|
||||
'@fastify/cors@11.0.0':
|
||||
dependencies:
|
||||
fastify-plugin: 5.0.1
|
||||
toad-cache: 3.7.0
|
||||
mnemonist: 0.40.0
|
||||
|
||||
'@fastify/csrf-protection@7.1.0':
|
||||
dependencies:
|
||||
@@ -12722,6 +12731,8 @@ snapshots:
|
||||
- eslint-import-resolver-webpack
|
||||
- supports-color
|
||||
|
||||
'@nhcarrigan/logger@1.1.1': {}
|
||||
|
||||
'@noble/hashes@1.4.0': {}
|
||||
|
||||
'@nodelib/fs.scandir@2.1.5':
|
||||
@@ -18229,6 +18240,10 @@ snapshots:
|
||||
dependencies:
|
||||
minipass: 7.1.2
|
||||
|
||||
mnemonist@0.40.0:
|
||||
dependencies:
|
||||
obliterator: 2.0.5
|
||||
|
||||
mnemonist@0.40.3:
|
||||
dependencies:
|
||||
obliterator: 2.0.5
|
||||
|
||||
Reference in New Issue
Block a user