Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@pujitm
Copy link
Member

@pujitm pujitm commented Nov 12, 2025

  • also adds util for reading ini configs synchronously

Summary by CodeRabbit

Release Notes

  • New Features

    • Added safe mode support to prevent plugin loading when enabled, returning an empty plugin list in safe mode.
  • Tests

    • Added comprehensive test coverage for safe mode functionality and state file loading mechanisms.

- also adds util for reading ini configs synchronously
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 12, 2025

Walkthrough

Changes introduce a safe-mode detection system with isSafeModeEnabled() utility that checks in-memory store state and falls back to file-based state loading via loadStateFileSync(). The plugin service is updated to skip loading when safe mode is active. Includes comprehensive test coverage.

Changes

Cohort / File(s) Change Summary
Safe Mode Utility
api/src/core/utils/safe-mode.ts, api/src/core/utils/__test__/safe-mode.test.ts
New exported function isSafeModeEnabled() that checks the in-memory store for emhttp.var.safeMode boolean, falls back to synchronously loading state from disk via loadStateFileSync(), and defaults to false. Includes three test cases covering store hit, file fallback, and null scenarios.
State File Loader
api/src/store/services/state-file-loader.ts, api/src/store/services/__test__/state-file-loader.test.ts
New exported function loadStateFileSync<K>() that reads .ini files from disk, parses them using per-key parser mappings, dispatches updates to the Redux store, and returns typed results. Includes tests for successful loads with safeMode detection, missing directory handling, and missing file handling.
Store Field Mapping
api/src/store/modules/emhttp.ts
Adds local stateFieldKeyMap mapping StateFileKey values to SliceState keys; updates updateEmhttpState reducer to use mapped target field instead of raw field when available.
Plugin Service Integration
api/src/unraid-api/plugin/plugin.service.ts, api/src/unraid-api/plugin/__test__/plugin.service.test.ts
Integrates isSafeModeEnabled() check into getPlugins() to return empty array and skip plugin imports when safe mode is active. Includes tests verifying safe mode short-circuits loading and normal mode proceeds as before.

Sequence Diagram(s)

sequenceDiagram
    participant Consumer as Client Code
    participant ISM as isSafeModeEnabled()
    participant Store as Redux Store
    participant FSL as loadStateFileSync()
    participant FS as File System
    
    Consumer->>ISM: Check safe mode
    ISM->>Store: Get state.emhttp.var.safeMode
    alt safeMode is boolean
        Store-->>ISM: Return value
        ISM-->>Consumer: Boolean result
    else safeMode undefined/missing
        ISM->>FSL: Load var state from file
        FSL->>FS: Read var.ini from states dir
        alt File found
            FS-->>FSL: Content loaded
            FSL->>FSL: Parse ini content
            FSL->>Store: Dispatch updateEmhttpState
            FSL-->>ISM: Return parsed state
            ISM-->>Consumer: Boolean(varState.safeMode)
        else File missing or error
            FS-->>FSL: Error/null
            FSL-->>ISM: null
            ISM-->>Consumer: false (default)
        end
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Field mapping logic in emhttp.ts reducer warrants verification that the stateFieldKeyMap correctly associates all relevant StateFileKey values to their corresponding SliceState paths.
  • State file loader error handling is broad (try-catch returning null); review that file I/O edge cases (permission issues, malformed ini) are handled gracefully.
  • Safe mode integration in PluginService involves conditional control flow; confirm that the lazy initialization and logging don't introduce unintended side effects or double-initialization scenarios.

Poem

🐰 A hop and a check, safe mode's in place,
Files spin from disk, state finds its space,
Plugins now pause when caution takes hold,
Redux maps fields, a story retold! 🔐

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'fix: respect OS safe mode in plugin loader' accurately describes the main change: implementing safe mode detection in the plugin loading system. It is concise, specific, and clearly summarizes the primary objective.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/safe-mode

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link

codecov bot commented Nov 12, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 52.80%. Comparing base (c4cd0c6) to head (3c1d30f).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1775      +/-   ##
==========================================
+ Coverage   52.69%   52.80%   +0.10%     
==========================================
  Files         865      867       +2     
  Lines       49346    49434      +88     
  Branches     4952     4974      +22     
==========================================
+ Hits        26003    26103     +100     
+ Misses      23270    23258      -12     
  Partials       73       73              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions
Copy link
Contributor

This plugin has been deployed to Cloudflare R2 and is available for testing.
Download it at this URL:

https://preview.dl.unraid.net/unraid-api/tag/PR1775/dynamix.unraid.net.plg

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
api/src/unraid-api/plugin/__test__/plugin.service.test.ts (1)

6-11: Consider exposing test hooks instead of casting to private API.

While the type casting approach works, consider adding a reset method or test-only hooks to PluginService to avoid coupling tests to internal implementation details.

Apply this pattern in the service:

// In plugin.service.ts
static resetForTesting() {
    if (process.env.NODE_ENV === 'test') {
        PluginService.plugins = undefined;
    }
}
api/src/store/services/state-file-loader.ts (1)

78-80: Consider logging errors before returning null.

The catch block silently returns null without logging the error. This might make debugging difficult if state file loading fails during bootstrap.

Consider adding logging:

     } catch (error) {
+        // Could add logging here if needed for debugging
+        // stateFileLogger.debug('Failed to load state file %s: %s', stateFileKey, error);
         return null;
     }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c4cd0c6 and 3c1d30f.

📒 Files selected for processing (7)
  • api/src/core/utils/__test__/safe-mode.test.ts (1 hunks)
  • api/src/core/utils/safe-mode.ts (1 hunks)
  • api/src/store/modules/emhttp.ts (2 hunks)
  • api/src/store/services/__test__/state-file-loader.test.ts (1 hunks)
  • api/src/store/services/state-file-loader.ts (1 hunks)
  • api/src/unraid-api/plugin/__test__/plugin.service.test.ts (1 hunks)
  • api/src/unraid-api/plugin/plugin.service.ts (2 hunks)
🧰 Additional context used
📓 Path-based instructions (8)
**/{store,stores}/**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/web-testing-rules.mdc)

In store files, explicitly import Vue reactivity utilities (e.g., computed, ref, watchEffect); do not rely on Nuxt auto-imports

Files:

  • api/src/store/modules/emhttp.ts
  • api/src/store/services/__test__/state-file-loader.test.ts
  • api/src/store/services/state-file-loader.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Use TypeScript import specifiers with .js extensions for ESM compatibility
Never use the any type; prefer precise typing
Avoid type casting; model proper types from the start

Files:

  • api/src/store/modules/emhttp.ts
  • api/src/unraid-api/plugin/__test__/plugin.service.test.ts
  • api/src/store/services/__test__/state-file-loader.test.ts
  • api/src/core/utils/safe-mode.ts
  • api/src/store/services/state-file-loader.ts
  • api/src/unraid-api/plugin/plugin.service.ts
  • api/src/core/utils/__test__/safe-mode.test.ts
api/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

cache-manager v7 TTL values must be in milliseconds (e.g., 600000 for 10 minutes)

Files:

  • api/src/store/modules/emhttp.ts
  • api/src/unraid-api/plugin/__test__/plugin.service.test.ts
  • api/src/store/services/__test__/state-file-loader.test.ts
  • api/src/core/utils/safe-mode.ts
  • api/src/store/services/state-file-loader.ts
  • api/src/unraid-api/plugin/plugin.service.ts
  • api/src/core/utils/__test__/safe-mode.test.ts
api/src/unraid-api/**

📄 CodeRabbit inference engine (.cursor/rules/api-rules.mdc)

Prefer adding new files to the Nest repo at api/src/unraid-api/ instead of legacy code

Files:

  • api/src/unraid-api/plugin/__test__/plugin.service.test.ts
  • api/src/unraid-api/plugin/plugin.service.ts
api/**/*.{test,spec}.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/api-rules.mdc)

api/**/*.{test,spec}.{js,jsx,ts,tsx}: Use Vitest for tests in the api; do not use Jest
Prefer not to mock simple dependencies in tests
For error testing, use .rejects.toThrow() without arguments; avoid asserting exact error messages unless the message format is the subject under test

Files:

  • api/src/unraid-api/plugin/__test__/plugin.service.test.ts
  • api/src/store/services/__test__/state-file-loader.test.ts
  • api/src/core/utils/__test__/safe-mode.test.ts
{**/*.test.ts,**/__test__/{components,store}/**/*.ts}

📄 CodeRabbit inference engine (.cursor/rules/web-testing-rules.mdc)

{**/*.test.ts,**/__test__/{components,store}/**/*.ts}: Use .rejects.toThrow() without arguments when asserting that async functions throw; avoid checking exact error message strings unless the message format is explicitly under test
Focus tests on observable behavior and outcomes, not implementation details such as exact error messages
Use await nextTick() for DOM update assertions and flushPromises() for complex async chains; always await async operations before asserting
Place module mock declarations (vi.mock) at the top level of the test file to avoid hoisting issues
Use factory functions in vi.mock calls to define mocks and avoid hoisting pitfalls
Use vi.spyOn() to specify return values or behavior of methods under test
Reset/clear mocks between tests using vi.clearAllMocks() (and vi.resetAllMocks() when appropriate) to ensure isolation
Do not rely on Nuxt auto-imports in tests; import required Vue utilities explicitly in test files
Remember that vi.mock calls are hoisted; avoid mixing mock declarations and module mocks incorrectly

Files:

  • api/src/unraid-api/plugin/__test__/plugin.service.test.ts
  • api/src/store/services/__test__/state-file-loader.test.ts
  • api/src/core/utils/__test__/safe-mode.test.ts
api/**/*.{test,spec}.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

api/**/*.{test,spec}.{ts,tsx}: API test suite is Vitest; do not use Jest
Prefer not to mock simple dependencies in API tests

Files:

  • api/src/unraid-api/plugin/__test__/plugin.service.test.ts
  • api/src/store/services/__test__/state-file-loader.test.ts
  • api/src/core/utils/__test__/safe-mode.test.ts
{api,web}/**/*.{test,spec}.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

{api,web}/**/*.{test,spec}.{ts,tsx}: For error tests, use .rejects.toThrow() without arguments; avoid asserting exact error messages unless that format is the subject
Focus tests on behavior, not implementation details
Avoid brittle tests tied to exact error or log wording
Use mocks as nouns, not verbs
Always await async operations before making assertions
Place all mock declarations at the top level; use factory functions for module mocks; clear mocks between tests

Files:

  • api/src/unraid-api/plugin/__test__/plugin.service.test.ts
  • api/src/store/services/__test__/state-file-loader.test.ts
  • api/src/core/utils/__test__/safe-mode.test.ts
🧠 Learnings (24)
📚 Learning: 2025-08-11T15:10:28.150Z
Learnt from: CR
Repo: unraid/api PR: 0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-08-11T15:10:28.150Z
Learning: Applies to **/__test__/components/**/*.ts : Mock external dependencies and services in component tests (e.g., vi.mock for helper modules)

Applied to files:

  • api/src/unraid-api/plugin/__test__/plugin.service.test.ts
  • api/src/store/services/__test__/state-file-loader.test.ts
📚 Learning: 2025-09-12T01:36:59.838Z
Learnt from: CR
Repo: unraid/api PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-12T01:36:59.838Z
Learning: Applies to web/__test__/**/*.{test,spec}.{ts,tsx} : Mock external dependencies and services in component tests

Applied to files:

  • api/src/unraid-api/plugin/__test__/plugin.service.test.ts
📚 Learning: 2025-08-11T15:10:28.150Z
Learnt from: CR
Repo: unraid/api PR: 0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-08-11T15:10:28.150Z
Learning: Applies to **/__test__/store/**/*.ts : In store tests, mock external dependencies used by the store and verify interactions with those mocks

Applied to files:

  • api/src/unraid-api/plugin/__test__/plugin.service.test.ts
  • api/src/store/services/__test__/state-file-loader.test.ts
  • api/src/core/utils/__test__/safe-mode.test.ts
📚 Learning: 2025-08-11T15:10:28.150Z
Learnt from: CR
Repo: unraid/api PR: 0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-08-11T15:10:28.150Z
Learning: Applies to {**/*.test.ts,**/__test__/{components,store}/**/*.ts} : Use factory functions in vi.mock calls to define mocks and avoid hoisting pitfalls

Applied to files:

  • api/src/unraid-api/plugin/__test__/plugin.service.test.ts
  • api/src/store/services/__test__/state-file-loader.test.ts
  • api/src/core/utils/__test__/safe-mode.test.ts
📚 Learning: 2025-08-11T15:10:28.150Z
Learnt from: CR
Repo: unraid/api PR: 0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-08-11T15:10:28.150Z
Learning: Applies to **/__test__/mocks/**/*.ts : Frequently used mocks can also be placed under __test__/mocks

Applied to files:

  • api/src/unraid-api/plugin/__test__/plugin.service.test.ts
📚 Learning: 2025-09-12T01:36:59.838Z
Learnt from: CR
Repo: unraid/api PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-12T01:36:59.838Z
Learning: Applies to {api,web}/**/*.{test,spec}.{ts,tsx} : Place all mock declarations at the top level; use factory functions for module mocks; clear mocks between tests

Applied to files:

  • api/src/unraid-api/plugin/__test__/plugin.service.test.ts
📚 Learning: 2025-09-12T01:36:59.838Z
Learnt from: CR
Repo: unraid/api PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-12T01:36:59.838Z
Learning: Applies to api/**/*.{test,spec}.{ts,tsx} : Prefer not to mock simple dependencies in API tests

Applied to files:

  • api/src/unraid-api/plugin/__test__/plugin.service.test.ts
📚 Learning: 2025-09-12T01:36:59.838Z
Learnt from: CR
Repo: unraid/api PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-12T01:36:59.838Z
Learning: Applies to {api,web}/**/*.{test,spec}.{ts,tsx} : Focus tests on behavior, not implementation details

Applied to files:

  • api/src/unraid-api/plugin/__test__/plugin.service.test.ts
📚 Learning: 2025-08-11T15:10:28.150Z
Learnt from: CR
Repo: unraid/api PR: 0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-08-11T15:10:28.150Z
Learning: Applies to **/__test__/store/**/*.ts : In store tests, verify action side effects and state changes, and assert that actions are called with the correct parameters

Applied to files:

  • api/src/unraid-api/plugin/__test__/plugin.service.test.ts
  • api/src/store/services/__test__/state-file-loader.test.ts
  • api/src/core/utils/__test__/safe-mode.test.ts
📚 Learning: 2025-08-11T15:10:28.150Z
Learnt from: CR
Repo: unraid/api PR: 0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-08-11T15:10:28.150Z
Learning: Applies to {**/*.test.ts,**/__test__/{components,store}/**/*.ts} : Remember that vi.mock calls are hoisted; avoid mixing mock declarations and module mocks incorrectly

Applied to files:

  • api/src/unraid-api/plugin/__test__/plugin.service.test.ts
  • api/src/store/services/__test__/state-file-loader.test.ts
  • api/src/core/utils/__test__/safe-mode.test.ts
📚 Learning: 2025-09-12T01:36:59.838Z
Learnt from: CR
Repo: unraid/api PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-12T01:36:59.838Z
Learning: Applies to api/**/*.{test,spec}.{ts,tsx} : API test suite is Vitest; do not use Jest

Applied to files:

  • api/src/unraid-api/plugin/__test__/plugin.service.test.ts
📚 Learning: 2025-08-11T15:10:28.150Z
Learnt from: CR
Repo: unraid/api PR: 0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-08-11T15:10:28.150Z
Learning: Applies to {**/*.test.ts,**/__test__/{components,store}/**/*.ts} : Reset/clear mocks between tests using vi.clearAllMocks() (and vi.resetAllMocks() when appropriate) to ensure isolation

Applied to files:

  • api/src/unraid-api/plugin/__test__/plugin.service.test.ts
  • api/src/core/utils/__test__/safe-mode.test.ts
📚 Learning: 2025-08-11T15:10:28.150Z
Learnt from: CR
Repo: unraid/api PR: 0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-08-11T15:10:28.150Z
Learning: Applies to {**/*.test.ts,**/__test__/{components,store}/**/*.ts} : Use vi.spyOn() to specify return values or behavior of methods under test

Applied to files:

  • api/src/unraid-api/plugin/__test__/plugin.service.test.ts
📚 Learning: 2025-08-11T15:10:28.150Z
Learnt from: CR
Repo: unraid/api PR: 0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-08-11T15:10:28.150Z
Learning: This Nuxt app is tested with vitest outside the Nuxt runtime; structure tests accordingly

Applied to files:

  • api/src/unraid-api/plugin/__test__/plugin.service.test.ts
  • api/src/store/services/__test__/state-file-loader.test.ts
  • api/src/core/utils/__test__/safe-mode.test.ts
📚 Learning: 2025-08-11T15:10:28.150Z
Learnt from: CR
Repo: unraid/api PR: 0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-08-11T15:10:28.150Z
Learning: Applies to **/__test__/store/**/*.ts : Thoroughly test async store actions: assert intermediate loading state, await completion, and check final state

Applied to files:

  • api/src/store/services/__test__/state-file-loader.test.ts
  • api/src/store/services/state-file-loader.ts
  • api/src/core/utils/__test__/safe-mode.test.ts
📚 Learning: 2025-09-12T01:36:59.838Z
Learnt from: CR
Repo: unraid/api PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-12T01:36:59.838Z
Learning: Applies to web/__test__/**/*.{test,spec}.{ts,tsx} : Let stores initialize with natural default state; don’t mock the store under test

Applied to files:

  • api/src/store/services/__test__/state-file-loader.test.ts
  • api/src/core/utils/__test__/safe-mode.test.ts
📚 Learning: 2025-08-11T15:10:28.150Z
Learnt from: CR
Repo: unraid/api PR: 0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-08-11T15:10:28.150Z
Learning: Applies to **/__test__/store/**/*.ts : Do not mock the store under test; allow the store to initialize with its natural default state

Applied to files:

  • api/src/store/services/__test__/state-file-loader.test.ts
  • api/src/core/utils/__test__/safe-mode.test.ts
📚 Learning: 2025-08-11T15:10:28.150Z
Learnt from: CR
Repo: unraid/api PR: 0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-08-11T15:10:28.150Z
Learning: Applies to **/__test__/store/**/*.ts : Test computed properties/getters by accessing them directly and verifying derived state

Applied to files:

  • api/src/store/services/__test__/state-file-loader.test.ts
  • api/src/core/utils/__test__/safe-mode.test.ts
📚 Learning: 2025-08-11T15:10:28.150Z
Learnt from: CR
Repo: unraid/api PR: 0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-08-11T15:10:28.150Z
Learning: Applies to {**/*.test.ts,**/__test__/{components,store}/**/*.ts} : Place module mock declarations (vi.mock) at the top level of the test file to avoid hoisting issues

Applied to files:

  • api/src/store/services/__test__/state-file-loader.test.ts
  • api/src/core/utils/__test__/safe-mode.test.ts
📚 Learning: 2025-09-12T01:36:59.838Z
Learnt from: CR
Repo: unraid/api PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-12T01:36:59.838Z
Learning: Applies to web/__test__/**/*.{test,spec}.{ts,tsx} : Use createTestingPinia() for mocking stores in components

Applied to files:

  • api/src/store/services/__test__/state-file-loader.test.ts
📚 Learning: 2025-02-24T14:51:21.328Z
Learnt from: elibosley
Repo: unraid/api PR: 1181
File: web/store/theme.ts:0-0
Timestamp: 2025-02-24T14:51:21.328Z
Learning: In the Unraid API project's theme system, exact TypeScript type definitions are preferred over index signatures for theme variables to ensure better type safety.

Applied to files:

  • api/src/unraid-api/plugin/plugin.service.ts
📚 Learning: 2025-08-11T15:10:28.150Z
Learnt from: CR
Repo: unraid/api PR: 0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-08-11T15:10:28.150Z
Learning: Applies to {**/*.test.ts,**/__test__/{components,store}/**/*.ts} : Focus tests on observable behavior and outcomes, not implementation details such as exact error messages

Applied to files:

  • api/src/core/utils/__test__/safe-mode.test.ts
📚 Learning: 2025-09-12T01:36:59.838Z
Learnt from: CR
Repo: unraid/api PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-12T01:36:59.838Z
Learning: Applies to web/__test__/**/*.{test,spec}.{ts,tsx} : Test component behavior and output, not implementation details

Applied to files:

  • api/src/core/utils/__test__/safe-mode.test.ts
📚 Learning: 2025-08-11T15:10:28.150Z
Learnt from: CR
Repo: unraid/api PR: 0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-08-11T15:10:28.150Z
Learning: Applies to {**/*.test.ts,**/__test__/{components,store}/**/*.ts} : Do not rely on Nuxt auto-imports in tests; import required Vue utilities explicitly in test files

Applied to files:

  • api/src/core/utils/__test__/safe-mode.test.ts
🧬 Code graph analysis (5)
api/src/store/services/__test__/state-file-loader.test.ts (2)
api/src/store/index.ts (1)
  • store (10-16)
api/src/store/services/state-file-loader.ts (1)
  • loadStateFileSync (49-81)
api/src/core/utils/safe-mode.ts (2)
api/src/store/index.ts (1)
  • store (10-16)
api/src/store/services/state-file-loader.ts (1)
  • loadStateFileSync (49-81)
api/src/store/services/state-file-loader.ts (3)
api/src/store/index.ts (1)
  • store (10-16)
api/src/core/utils/misc/parse-config.ts (1)
  • parseConfig (146-203)
api/src/store/modules/emhttp.ts (2)
  • updateEmhttpState (182-192)
  • SliceState (21-32)
api/src/unraid-api/plugin/plugin.service.ts (1)
api/src/core/utils/safe-mode.ts (1)
  • isSafeModeEnabled (5-17)
api/src/core/utils/__test__/safe-mode.test.ts (2)
api/src/store/index.ts (1)
  • store (10-16)
api/src/core/utils/safe-mode.ts (1)
  • isSafeModeEnabled (5-17)
🔇 Additional comments (10)
api/src/store/modules/emhttp.ts (2)

166-176: LGTM! Clean mapping of state file keys to slice fields.

The stateFieldKeyMap correctly translates StateFileKey enum values to their corresponding SliceState field names, enabling the synchronous state loader to dispatch updates using the file-based keys.


190-191: LGTM! Reducer correctly applies the field mapping.

The updated reducer uses the mapping to determine the target field, with a sensible fallback for unmapped keys. This enables the state-file-loader to update the store using StateFileKey values.

api/src/core/utils/safe-mode.ts (1)

5-17: LGTM! Clean safe-mode detection with sensible fallbacks.

The function correctly checks in-memory store state first, falls back to synchronous file loading when needed, and defaults to false if neither source is available. The type guard on line 7 prevents treating non-boolean values as safe-mode flags.

api/src/unraid-api/plugin/plugin.service.ts (1)

24-33: LGTM! Safe-mode check properly gates plugin loading.

The updated lazy initialization correctly checks safe mode before loading plugins, logging an informative warning and returning an empty array when safe mode is active. This preserves the singleton pattern while respecting OS-level safe mode.

api/src/core/utils/__test__/safe-mode.test.ts (1)

7-66: LGTM! Comprehensive test coverage for safe-mode detection.

The test suite properly validates all three code paths: store state present, fallback to file loader, and default false. Mock usage follows best practices with proper restoration in afterEach, and the type casting is acceptable for simulating edge cases in tests.

api/src/unraid-api/plugin/__test__/plugin.service.test.ts (1)

13-46: LGTM! Tests properly verify safe-mode behavior.

The test suite correctly validates that plugin loading is skipped when safe mode is enabled and proceeds normally when disabled. Mock usage and state reset between tests follows best practices.

api/src/store/services/__test__/state-file-loader.test.ts (2)

11-16: LGTM! Clean fixture management.

The fixture loading and helper function provide a flexible way to test different safe-mode values while maintaining realistic test data.


18-81: LGTM! Comprehensive test coverage with proper cleanup.

The test suite validates all critical paths: successful loading with store updates, graceful handling of missing configuration, and missing files. Temporary directory management with cleanup ensures test isolation.

api/src/store/services/state-file-loader.ts (2)

19-41: LGTM! Well-typed parser infrastructure.

The ParserReturnMap and PARSER_MAP provide strong typing for the synchronous loader while avoiding dynamic imports. This is appropriate for bootstrap contexts where async loading is impractical.


49-81: LGTM! Synchronous loader correctly handles bootstrap constraints.

The function appropriately handles missing configuration by returning null, dispatches store updates as documented, and returns the parsed state. The type casting on line 68 is necessary due to TypeScript's limitations with complex generic constraints.

@pujitm pujitm marked this pull request as ready for review November 12, 2025 21:22
@pujitm pujitm requested a review from elibosley November 12, 2025 21:22
Copy link
Member

@elibosley elibosley left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work on this!

@pujitm pujitm merged commit 92af3b6 into main Nov 13, 2025
13 checks passed
@pujitm pujitm deleted the fix/safe-mode branch November 13, 2025 15:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants