Commit Graph
258 Commits
Author SHA1 Message Date
DarkraiseandGitHub 4594a66721 Merge pull request #10 from darkraise/feature/pagination-enhancement
feat: add server-side pagination to all list endpoints
2026-02-15 01:16:10 +07:00
Darkraise b2456efe40 fix: fetch all local playlists for duplicate detection 2026-02-15 01:15:57 +07:00
Darkraise d0681ef3ab feat: add server-side pagination to all list endpoints
Add page-based pagination with proper total counts to:
- Favorites games endpoint (backend + frontend)
- Community playlists endpoint (backend + frontend)
- User playlists endpoint (backend + frontend)
- Roles endpoint (backend + frontend)

Changes include:
- Backend routes now accept page/limit params and return
  { data, pagination } response format
- Services return { data, total } for paginated queries
- Frontend hooks updated with page/limit parameters
- Views display PaginationWithInfo component when needed
- DataTable uses shared Pagination component
- Mutation hooks use invalidateQueries instead of manual
  cache updates for consistency with paginated data
- Increase default siblingCount to 2 in Pagination
2026-02-15 01:04:51 +07:00
Darkraise ea2d913766 fix: preserve search params during auth redirect
When a protected page includes query parameters (e.g., filters,
pagination), they were lost after login because only pathname was
extracted from location state. Now both pathname and search params
are preserved when redirecting back after authentication.
2026-02-14 20:45:11 +07:00
DarkraiseandGitHub 1dea285285 Merge pull request #9 from darkraise/feature/html5-game-enhancement
fix: improve HTML5 game compatibility and auth redirects
2026-02-14 20:08:47 +07:00
Darkraise 37d6ee239c fix: prevent open redirect in login return URL handling
- Add isValidReturnUrl() helper in LoginForm.tsx
- Add sanitizeRedirectPath() helper in AuthContext.tsx
- Apply sanitization to both regular login and guest login flows
2026-02-14 20:07:30 +07:00
Darkraise a990db1ce2 fix: improve HTML5 game compatibility and auth redirects
- Add COEP headers for iframe embedding when parent has COEP enabled
- Remove URL encoding in game proxy path (handler expects raw URLs)
- Preserve returnUrl as query param across cross-browser navigation
- Pass redirect path to loginAsGuest for proper return after login
- Filter play history to only return completed sessions
- Add documentation for CORS header responsibilities
2026-02-14 16:47:57 +07:00
Darkraise c62354fc7d chore: update contributing guide 2026-02-14 12:29:26 +07:00
Darkraise d70d86b572 chore: update contributing guide 2026-02-14 11:48:35 +07:00
Darkraise 1ebe55badc chore: update github actions 2026-02-14 11:25:08 +07:00
DarkraiseandGitHub 39bc35b9d5 Merge pull request #8 from darkraise/feature/metadata-sync
feat: improve metadata sync compatibility across Flashpoint editions
2026-02-13 22:08:11 +07:00
Darkraise 4714aeed32 feat: improve metadata sync compatibility across Flashpoint editions
- Replace hardcoded edition check with runtime schema introspection to
  detect available game columns dynamically
- Move GameMetadataSource type to PreferencesService for reuse across
  sync and update services
- Add hasMetadataSource() check instead of edition-based feature gating
- Handle orphaned parent references by nullifying parentGameId when
  parent doesn't exist in batch or database
- Disable foreign key checks during bulk insert/delete operations to
  match Flashpoint Launcher behavior
- Build combined Ruffle changelog showing all changes since current
  version instead of just latest release
- Add skeleton loading state to MetadataUpdateCard during initial fetch
- Reduce per-game cycle warning spam to single summary log
2026-02-13 21:54:47 +07:00
DarkraiseandGitHub 5d91fcf6bd Merge pull request #7 from darkraise/feature/ui-enhancement
Feature/UI enhancement
2026-02-13 02:08:02 +07:00
Darkraise dcb597624b fix: improve test mocks and type safety for random game feature
- Fix platform filter to properly trim strings in array format
- Remove redundant breadcrumb context from random game navigation
- Add comprehensive tests for useRandomGame hook
- Reorder mock handlers to place static routes before parameterized
- Add explicit type annotation to breadcrumb items array
2026-02-13 02:07:49 +07:00
Darkraise 9c472392fe feat: enhance UI with glassmorphism and improve navigation context
- Add glassmorphism effect to dialog, sheet, popover, dropdown, and
  alert-dialog components with backdrop blur and subtle borders
- Improve sidebar highlighting by prioritizing breadcrumb context over
  URL prefix matching for accurate section detection
- Add parent breadcrumb support for nested navigation (e.g., Flashpoint
  Playlists > Playlist Name > Game)
- Replace "Back to" links with consistent Breadcrumbs component in
  playlist detail views
- Add platform filter to random game endpoint (limit Lucky button to
  Flash/HTML5)
- Remove unused role priority field from schema, types, and UI
- Sort roles table with system roles pinned at top, show "System Role"
  badge instead of disabled actions
2026-02-13 01:19:11 +07:00
Darkraise d2931f3942 feat: add section-based routing with contextual breadcrumbs
Introduce URL-based navigation structure where games retain their
section context (/flash/:id, /html5/:id, /animations/:id, /browse/:id).

Key changes:
- Shorten route paths: /flash-games -> /flash, /html5-games -> /html5
- Add sectionRoutes.ts with centralized section configuration
- Update sidebar active state detection to track section routes
- Enhance Breadcrumbs component with icon support and sticky styling
- Derive breadcrumb context from URL path, falling back to state
- Remove unused imports across backend files
2026-02-12 21:43:20 +07:00
Darkraise da6bbbb526 feat: enhance UI with toast progress bars and lucky button animations
- Add progress bar indicator to toast notifications showing auto-dismiss
  countdown, pauses on hover for improved UX
- Add close button to toasts with proper styling per toast type
- Enhance "Feeling Lucky" button with bounce animation, ping effect,
  and smooth hover/active transitions
- Update favicon to official Flashpoint branding
- Convert Tailwind config to use ESM imports instead of require()
2026-02-12 11:02:02 +07:00
Darkraise dd80da7d44 chore: update CLAUDE.md 2026-02-11 23:29:04 +07:00
DarkraiseandGitHub 86822739de Merge pull request #6 from darkraise/feature/code-review
Feature/code review
2026-02-11 22:07:12 +07:00
Darkraise 13af889a1e fix: improve settings validation and sidebar responsiveness
- Replace generic Error with AppError for proper HTTP status codes
  in SystemSettingsService validation (400 for client errors, 404
  for missing settings, 500 for schema errors)
- Add useMediaQuery hook for reactive viewport tracking
- Replace window.innerWidth checks with useMediaQuery in Sidebar
  to properly react to viewport changes
- Make currentPassword optional in ChangePasswordData type to
  support admin password resets
2026-02-11 22:03:53 +07:00
Darkraise 79cc256214 fix: harden downloads, settings, and UI edge cases
- Integrate DownloadRegistry into concurrent download limit
  and clean up timers on removal/clear
- Wrap MetadataSyncService batch deletes in single transaction
- Always re-throw checksum errors in RuffleService to prevent
  verification bypass
- Fix system-settings early return skipping second job update
  when first cron expression is invalid
- Increase DatabaseService hot-reload grace period to 30s
- Add permission guard to metadata sync status endpoint
- Use encodeURIComponent for game launch content URLs
- Clamp limit params to minimum of 1 in jobs routes
- Use non-null assertion for authenticated user permissions
- Fix ConfirmDialog not calling onCancel on overlay dismiss
- Guard FormattedDate against invalid date strings
- Add breadcrumbContext to GameListItem memo comparison
- Fix MetadataUpdateCard stale closure in interval callback
- Move Dockerfile healthcheck to docker-compose for flexibility
- Fix build:analyze script to set VITE_ANALYZE env var
2026-02-11 20:37:06 +07:00
Darkraise f281672faa chore: remove unused docs 2026-02-11 19:11:01 +07:00
Darkraise 06308a198d perf: cache filter options and pre-warm at startup
The 8 GROUP BY queries (~1.8s) for filter options now
run once at startup and cache indefinitely. Cache is
invalidated on DB reload and force sync.
2026-02-11 19:10:05 +07:00
Darkraise cbc94db79c feat: add shared download registry, type safety, and test infra
feat: add shared download registry, type safety, and test infra

Add DownloadRegistry to prevent duplicate downloads between
DownloadManager and GameZipServer. Consolidate PreferencesService
(delete game/services copy, add compatibility aliases). Replace
`any` defaults with `unknown` in DatabaseService/UserDatabaseService
and add explicit type parameters to ~40 query call sites. Add
vitest config, test setup, test helpers, and unit tests for auth
middleware, RBAC, pagination, and time range utils. Enable
strictPropertyInitialization in backend tsconfig. Add SHA-256
checksum verification to RuffleService updates. Harden Docker
Compose with log rotation, resource limits, and bridge network.
Fix NODE_ENV default in dev compose, exclude guest userId from
activity logs, add activity logging to password change, guard
nullable permission descriptions, and align frontend Game/Permission
types with actual API shape.
2026-02-11 14:43:00 +07:00
Darkraise 6989924891 fix: add radix to parseInt, remove dead code, and guard invalid dates
- Add explicit radix 10 to all parseInt() calls across
  backend routes and frontend utilities
- Remove unused exports: normalizePagination, queryParser,
  getStartDateFromTimeRange, getAllIconNames, logIconValidation,
  isValidIconName, and lib/index.ts barrel file
- Guard against division-by-zero in createPaginatedResponse
- Add isNaN(dateObj) checks in useDateTimeFormat formatters
- Remove unnecessary try-catch in FormattedDate component
- Use nullish coalescing (??) for date/time format defaults
- Narrow export scope: make internal helpers private
2026-02-10 22:03:47 +07:00
Darkraise 75c69a3210 chore: clean up Docker and build config
- Move health check from Dockerfile to docker-compose
  for easier override
- Remove unused VITE_API_URL build arg from frontend
  Dockerfile
- Simplify build:analyze and check-bundle scripts
- Document PUID/PGID container permissions in
  .env.example
2026-02-10 21:19:25 +07:00
Darkraise 3e35799de8 fix: standardize imports, tighten types, and align
mock data with actual API contracts

- Normalize all `cn` imports to `@/lib/utils` across
  30+ UI and component files
- Replace relative imports with `@/` alias in auth,
  roles, users, stats, and layout components
- Remove redundant `as` type assertions in playlist
  routes (Zod parse already returns typed data)
- Replace `any` with proper types in FallbackCache,
  mock handlers, and validateIcons
- Use `type` import for type-only imports
- Add type-safe `.filter(Boolean)` with type guard
  in Sidebar nav item arrays
- Update MSW mock data to match actual API shape:
  numeric IDs, `role` field, HTTP-only cookie auth,
  paginated response format, and settings schema
- Add JSDoc to AuthTokens clarifying cookie-based
  token storage
- Replace console.* calls with logger in icon
  validation
- Ignore SQLite WAL files in .gitignore
2026-02-10 20:42:56 +07:00
Darkraise b95f058a66 fix: reduce log noise, harden DB reload, and tune caches
- Demote per-request game service logs to debug level
- Add reentrant guard to DatabaseService.syncAndReload
- Enable WAL mode + PRAGMA tuning for user.db
- Align CachedSystemSettingsService cleanup to 90s interval
- Extract CACHE_TTL constant in GameSearchCache
- Add PerformanceMetrics hourly cleanup with .unref()
- Fix migration timing to measure exec only, type result
- Add parseInt NaN fallback for OTEL metrics interval
- Make config object readonly with `as const`
2026-02-10 16:55:54 +07:00
Darkraise d4edd2829f fix: use theme tokens and fix types in UI components 2026-02-10 16:35:40 +07:00
Darkraise ba2c6b4ea1 fix: improve error handling, theme tokens, and type safety
- Add error reporting to all error boundary components
- Replace hardcoded colors with theme tokens (destructive,
  primary, amber) for dark mode compatibility
- Use `??` instead of `||` for config/setting defaults
- Replace `any` with `unknown` in asyncHandler types
- Add `Identifiable` constraint to createQueryHook generics
- Fix timeout leaks with useRef and componentWillUnmount
- Add `.catch()` on fire-and-forget promises
- Deduplicate theme sync logic into `maybeSyncToServer`
- Extract `resolveActualMode` helper in theme store
- Add Zustand `useShallow` selector to CardSizeControl
- Add axios module augmentation for custom request config
- Set 30s default timeout on API client
- Deduplicate toast IDs to prevent session-expired spam
- Fix TOAST_REMOVE_DELAY from 1000000ms to 1000ms
- Fix use-toast useEffect dependency array
- Remove redundant try/catch in asyncHandler-wrapped routes
- Lock body scroll when mobile sidebar is open
- Fix route ordering: static before wildcard in App.tsx
- Quote background-image URLs in LazyBackgroundImage
- Remove duplicate onCancel call in ConfirmDialog
- Add deferred TODO.md for architectural improvements
- Clear isMaintenanceMode on logout, stop persisting it
2026-02-10 12:06:47 +07:00
Darkraise 789355cb7e fix: validate inputs, harden services, and DRY
route handlers

- DRY timeRange validation into shared parseTimeRange()
- Add jobId format validation, cron schedule validation,
  and date format validation on route inputs
- Add auth middleware to update check/metadata endpoints
- Harden sync start with atomic tryStartSync() to prevent
  race conditions
- Add symlink escape prevention and SVG CSP headers to
  proxy routes
- Cache public settings in CachedSystemSettingsService
- Fix MetadataSyncService: validate allowed hosts (SSRF),
  batch deletes to avoid SQL variable limits, use ?? over
  || for nullable fields
- Remove unnecessary async from synchronous DB methods in
  GameDatabaseUpdater
- Add path traversal check in makeRelativePath()
- Prevent setting creation via set() — only allow updates
- Remove unused getJobStatus/getAllJobs, lastRunTimes map
- Strip internal paths from getSystemInfo() response
- Sanitize update error messages to avoid leaking stderr
- Add job log cleanup interval with unref()
- Replace hardcoded colors with theme tokens, fix React
  Fragment keys, use getErrorMessage() utility
- Convert MetadataUpdateCard ref to state for reactivity
- Use ?? instead of || for config defaults across settings
2026-02-09 23:37:25 +07:00
Darkraise 80e2177b5d fix: harden validation, DRY chart utils, and improve type safety
Backend:
- Add Zod UUID validation for game/playlist route params
- Fix parseInt NaN fallback in play-tracking query params
- Add password max-length (128) and self-delete prevention
- Whitelist sort direction to prevent SQL injection in
  FavoritesService
- Use ?? over || for yearFrom/yearTo and presentOnDisk
- Fix TOCTOU in updateUserStats with atomic UPSERT subqueries
- Encode game content URL, add 500MB download size limit
- Fix DownloadManager promise double-settlement with guard
- Add optionalAuth to public playlist routes
- Coerce isActive to boolean in UserService responses
- Delete user_stats row on user deletion
- Use single AuthService instance in UserService
- Fix SQL quoting (double → single quotes)

Frontend:
- Extract shared chart-utils (CHART_COLORS, formatPlaytimeCompact,
  truncateTitle, getCSSVar) from 3 chart components
- Replace hardcoded colors with theme-aware CSS variables in
  PlaytimeChart and TopGamesChart
- Wrap GameListItem in React.memo with custom comparator
- Move Statistics type to API layer, re-export from hook
- Type statisticsApi return value
- Add maxLength to playlist title/description inputs
- Fix ChangePasswordDialog: skip current password for admin
  resets, remove min-length on current password field
- Add max-length (128) to password fields across forms
- Validate roleId as positive integer in UserForm
- Replace hardcoded Tailwind colors with theme tokens
  (text-destructive, bg-destructive/10, border-destructive)
- Fix tag separator from semicolon to comma in browse layout
- Guard division-by-zero in GamesDistributionChart
- Simplify UserTable delete handler, remove duplicate toast
- Fix unused import (toast) in UserTable
2026-02-09 23:18:18 +07:00
Darkraise ab4f4bad41 fix: harden RBAC, add security headers, and prevent permission escalation
- Add permission escalation check to role create/update endpoints
  so users cannot assign permissions they do not possess
- Replace permissive `settings.view` with `settings.read` across
  cache, health, and metrics routes
- Require authentication and `playlists.create` for community
  playlist downloads (was `optionalAuth`)
- Add `X-Content-Type-Options: nosniff` and `X-Frame-Options`
  headers to game content responses
- Enable Content-Security-Policy via helmet with restrictive
  default-src and frame-ancestors directives
- Set `server.maxConnections = 500` as defense-in-depth limit
- Delete role atomically with its permissions in a transaction
  and invalidate permission cache afterward
- Unify registration error messages to prevent username/email
  enumeration
- Disable permission management for system roles in RoleTable
- Encode share tokens and game IDs in frontend API URLs
- Add `optionalAuth` to statistics route
- Remove unused `rateLimitAuth` export
2026-02-09 22:46:25 +07:00
DarkraiseandGitHub 71f0b16765 Merge pull request #5 from darkraise/feature/code-cleanup
Feature/code cleanup
2026-02-09 19:24:27 +07:00
Darkraise 4ccad41a81 refactor: clean up DataTable, fix nullish coalescing 2026-02-09 19:24:13 +07:00
Darkraise 2f641c8441 chore: comments cleanup 2026-02-09 17:26:17 +07:00
Darkraise e173ce721e refactor: move access token to HTTP-only cookie 2026-02-09 11:29:40 +07:00
Darkraise ee9c2a296f fix: harden security, improve type safety, and clean up code
- Pin DNS resolution to prevent SSRF rebinding between
  check and connect (GameDataDownloader)
- Fail-closed on realpath failure in GameZipServer
- Zip Slip validation before extraction (RuffleService)
- Escape LIKE wildcards in ActivityService queries
- Sanitize sort order to prevent SQL injection
- Whitelist sort order instead of passing raw user input
- Add headersSent guard to global error handler
- Remove cookie from CGI allowed headers, sanitize
  content-type against null/CR/LF injection
- Revoke refresh tokens on password change and user
  deactivation
- Wrap role/user uniqueness checks in transactions
  (TOCTOU fix)
- Fix concurrent ZIP mount race with deferred promise
  and double-close prevention via _manuallyClosed flag
- Handle client disconnect in collectRequestBody
- Tighten nginx CSP, repeat headers in location blocks,
  hide server version, pin nginx:1.27-alpine
- Fix health check endpoint path in backend Dockerfile
- Use wget instead of curl for frontend health checks
- Replace any types with proper types across backend
  and frontend
- Replace || with ?? for config/form defaults
- Replace hardcoded Tailwind colors with theme tokens
- Replace console.log/error with logger in ErrorReporter
  and ChartErrorBoundary
- Conditionally render AddToPlaylistModal to avoid
  hidden instances
- Add NaN guards for parseInt in GameBrowseLayout
- Standardize query key for publicSettings
- Simplify README to Docker-first quickstart with wiki
  link
- Fix license to GPL-3.0 in backend package.json
- Slow down particle animation speed
- Add Zod max-length limits on playlist/error schemas
- Ensure positive limit in parsePaginationQuery
- Validate settings category param against allowlist
- Fix static/parameterized route ordering in favorites
- Add asyncHandler to game-zip wildcard route
- Close readline/stream on error in getRecentErrors
- Add .catch() on fire-and-forget syncAndReload
- Fix LazyBackgroundImage cleanup on unmount
- Store NetworkStatusIndicator timeout in ref
- Add Flash/SWF condition to random game query
2026-02-09 09:17:18 +07:00
DarkraiseandGitHub bbfcaebf4d Merge pull request #4 from darkraise/feature/cgi-support
feat: add CGI/PHP support for legacy Flashpoint games
2026-02-08 08:26:21 +07:00
Darkraise 7d3d64903f fix: harden security, data integrity, and resource management
- Eliminate `new Promise(async ...)` anti-pattern in GameDataDownloader
- Add TOCTOU-safe transactions in DomainService, FavoritesService,
  DownloadManager, and UserService (cascading delete)
- Add path traversal protection in PlaylistService (UUID validation)
- Add Zip Slip protection and backup restore in RuffleService
- Escape LIKE wildcards in GameService search queries
- Cache ZIP entry metadata to avoid re-reading entries on every lookup
- Fix login lockout query to check username/IP independently
- Cache null values in CachedSystemSettingsService to avoid repeated
  DB queries for missing keys
- Chunk MetadataSyncService upserts to stay under SQLite variable limit
- Add GitHub stars endpoint caching (15min TTL) to respect rate limits
- Deduplicate concurrent proxy cache writes via pending-write tracking
- Prevent infinite retry loop in DatabaseService syncAndReload
- Fix `useEffect` dependency issues with callback refs in
  MaintenanceGuard, useLazyLoad, useSwipeGesture, GameDetailView
- Handle async errors in MaintenancePage polling and MetadataUpdateCard
- Add null-safe guards for dashboard statistics rendering
- Validate settings category, timeRange, and batch size limits
- Sanitize error messages to avoid leaking internals to clients
- Stream error log file reads instead of loading entire file into memory
- Narrow `SELECT u.*` to explicit columns in AuthService
- Remove `themeColor`/`surfaceColor` from auth response payload
- Fix "playlistGames" typo in UserPlaylistDetailView
- Tighten `isApiError` type guard to require status/code/response
- Add `maxContentLength` to external HTTP requests
- Add null-byte rejection in proxy path validation
- Use URL constructor for safe logo URL derivation
- Add shared playlist validation middleware to game validate endpoint
- Add `res.destroyed` checks in GameZipServer before/after async lookup
- Proper listener cleanup in proxy `collectRequestBody`
- Add `.unref()` to PermissionCache cleanup interval
- Add `SharedPlaylistView` auth gate for query enablement
2026-02-08 08:25:33 +07:00
Darkraise 96cf4a5b00 feat: revamp the game serving feature 2026-02-07 23:36:45 +07:00
Darkraise 492c049499 fix: improve CGI executor reliability and resource cleanup
- Clear force-kill timeout on process exit to prevent leaks
- Support LF-only line endings in CGI output parsing
- Add proper timeout handling for request body collection
- Save/restore env vars in tests to prevent pollution
2026-02-05 18:17:05 +07:00
Darkraise 8cde8a98eb feat: add CGI/PHP support for legacy Flashpoint games 2026-02-05 17:23:18 +07:00
DarkraiseandGitHub 1c80902fa1 Merge pull request #3 from darkraise/feature/domain-settings
Feature/domain settings
2026-02-05 16:38:49 +07:00
Darkraise a74bc8197d refactor: improve caching, cleanup jobs, and type safety
- Convert CachedSystemSettingsService to singleton pattern
- Add scheduled cleanup for login attempts (24h) and activity logs
- Add batch size limits (100) for favorites and playlist operations
- Enhance health check with game-service connectivity verification
- Add cache stampede prevention in GameSearchCache
- Fix N+1 query in RoleService.getRoles() with single JOIN query
- Consolidate domains migration into 001_complete_schema.sql
- Replace `any` types with `unknown` and explicit type parameters
- Extract MetadataUpdateCard and RuffleManagementCard components
- Fix race condition in PlayTrackingService duration calculation
2026-02-05 16:31:05 +07:00
Darkraise 996c17734b fix: harden security and improve code quality across services
fix: harden security and improve code quality across services

Add Zod validation schemas to backend routes, replace z.any() with
explicit types, and convert SQL string interpolation to parameterized
queries to prevent injection attacks.

Security improvements:
- Add SSRF protection with domain allowlist in CommunityPlaylistService
- Enforce JWT algorithm restriction and token type validation
- Sanitize error messages to prevent path leakage in game-service
- Add MIME type enforcement based on file extension, not server headers
- Add request timeouts with exponential backoff retry logic
- Prevent Flashpoint database writes (read-only enforcement)

Backend improvements:
- Use UPSERT for play tracking to avoid race conditions
- Add dispose() method to CachedSystemSettingsService for cleanup
- Use crypto.randomUUID() instead of custom UUID generator
- Batch fetch games in PlaylistService to fix N+1 query pattern
- Use centralized verifyPassword utility in UserService

Frontend improvements:
- Add PlayerErrorBoundary to prevent app crashes from Ruffle errors
- Add theme initialization script to prevent FOUC
- Add custom favicon.svg with Flashpoint branding
- Fix token refresh race condition with subscriber queue
- Add AbortSignal support to games search API
- Replace EventSource with fetch for authenticated SSE streams
- Improve error handling in UserForm and CreatePlaylistModal
- Stream large files instead of buffering in game-service
2026-02-05 10:29:03 +07:00
Darkraise af740d6dab fix: harden domain settings and share URL handling
- Add max domain limit (50) to prevent unbounded growth
- Auto-promote next domain as default when deleting current
  default inside a transaction
- Cache CORS allowed origins alongside domain cache
- Validate share URLs with URL constructor and restrict to
  http/https protocols
- Track per-domain delete state to avoid disabling all buttons
- Prevent domain selector reset after manual user selection
- Refetch domains after delete to reflect auto-promoted default
- Replace inline require() calls with top-level config import
- Add debug/warn logging for swallowed catch blocks
2026-02-04 22:48:42 +07:00
Darkraise 971b432d94 fix: code review issues 2026-02-04 16:57:48 +07:00
Darkraise 855cb8b38c refactor: convert DomainService to singleton pattern
Move cache state from module-level variables into instance
properties and use getInstance() to ensure a single shared
instance across routes and CORS configuration.
2026-02-04 11:23:20 +07:00
Darkraise afd835bbd9 refactor: update according to code review 2026-02-04 11:18:46 +07:00