Skip to content

Conversation

@elibosley
Copy link
Member

@elibosley elibosley commented Nov 20, 2025

Summary

  • ensure the API release build copies nodemon.json into the packaged artifacts so nodemon-managed deployments have the config available

Testing

  • pnpm --filter @unraid/api lint:fix

Codex Task

Summary by CodeRabbit

  • Refactor

    • Switched runtime/CLI tooling from PM2 to nodemon and removed PM2 readiness signaling.
    • CLI now uses a nodemon-backed service for start/stop/restart/status/logs.
  • New Features

    • Added nodemon configuration and a Nodemon management service with PID, logging and lifecycle handling.
  • Updates

    • Package/version endpoints and client schema report nodemon instead of pm2.
    • GraphQL adds per‑CPU package telemetry/topology; stop command flag changed to force (-f).
  • Tests

    • Removed PM2 tests; added nodemon service and nodemon-paths tests.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 20, 2025

Walkthrough

Replaces PM2 with nodemon across the API: removes PM2 config, service, helpers and tests; adds nodemon config, NodemonService and tests; updates environment paths, CLI wiring, GraphQL types, packaging, build script, and removes PM2 IPC ready signalling.

Changes

Cohort / File(s) Summary
Config & Packaging
api/ecosystem.config.json, api/nodemon.json, api/package.json, api/scripts/build.ts
Deletes PM2 ecosystem config; adds nodemon.json; removes pm2 dependency and adds nodemon to runtime deps; build script now copies nodemon.json and adjusts an import path.
Environment & Paths
api/src/environment.ts, api/src/__test__/environment.nodemon-paths.test.ts
Removes PM2-related exports (PM2_HOME, PM2_PATH, ECOSYSTEM_PATH); adds UNRAID_API_ROOT, NODEMON_PATH, NODEMON_CONFIG_PATH, NODEMON_PID_PATH, UNRAID_API_CWD; adds test validating nodemon paths.
Process detection utils & tests
api/src/core/utils/pm2/unraid-api-running.ts (deleted), api/src/core/utils/process/unraid-api-running.ts, api/src/__test__/core/utils/process/unraid-api-running.integration.test.ts, api/src/__test__/core/utils/pm2/* (deleted)
Removes PM2-based isUnraidApiRunning and PM2 test helpers; adds PID-file–based isUnraidApiRunning and corresponding integration tests using NODEMON_PID_PATH.
CLI services & tests
api/src/unraid-api/cli/pm2.service.ts (deleted), api/src/unraid-api/cli/pm2.service.spec.ts (deleted), api/src/unraid-api/cli/nodemon.service.ts, api/src/unraid-api/cli/nodemon.service.spec.ts
Removes PM2Service and its tests; introduces NodemonService with ensure/start/stop/restart/status/logs, PID and log-file management, execa spawning, and comprehensive unit tests.
CLI modules & commands
api/src/unraid-api/cli/cli.module.ts, api/src/unraid-api/cli/cli-services.module.ts, api/src/unraid-api/cli/*.command.ts, api/src/unraid-api/cli/__test__/report.command.test.ts
Replaces PM2Service with NodemonService in DI and commands; start/stop/restart/status/logs/report now delegate to NodemonService; stop flag changes from --delete to --force; tests updated to new import/terminology.
Application startup
api/src/unraid-api/main.ts
Removes PM2 IPC "ready" signalling via process.send from server startup.
GraphQL schema, models & resolvers
api/generated-schema.graphql, api/legacy/generated-schema-legacy.graphql, api/src/unraid-api/graph/resolvers/info/versions/versions.model.ts, api/src/unraid-api/graph/resolvers/info/versions/versions.resolver.ts
Replaces pm2 field with nodemon in schema, legacy schema, model and resolver (resolver sources nodemon from package.json).
Web GraphQL types & extras
web/composables/gql/graphql.ts, web/src/composables/gql/graphql.ts, web/src/composables/gql/index.ts
Generated types updated: remove pm2, add nodemon in PackageVersions; adds CpuPackages and extends InfoCpu/Subscription; minor export string quoting changes.
Core logging comments
api/src/core/log.ts
Minor comment wording updates only.
Misc tests & mocks
api/src/__test__/graphql/resolvers/rclone-api.service.test.ts
Extended test environment mock with SUPPRESS_LOGS and LOG_LEVEL; behavior otherwise unchanged.

Sequence Diagram(s)

sequenceDiagram
    participant CLI as CLI Command
    participant Nod as NodemonService
    participant FS as Filesystem (pid/log)
    participant Child as nodemon process

    rect `#ebf5ff`
    Note over CLI,Nod: Start flow (new)
    CLI->>Nod: ensureNodemonDependencies()
    Nod->>FS: mkdir logs & pid dirs (recursive)
    CLI->>Nod: start({ env })
    Nod->>Child: execa nodemon (detached, stdio piped)
    Child->>FS: write logfile, write PID -> nodemon.pid
    end

    rect `#e9ffeb`
    Note over CLI,Nod: Status / Stop / Restart
    CLI->>Nod: status()
    Nod->>FS: read nodemon.pid
    Nod->>Nod: process.kill(pid, 0) => alive? -> boolean
    CLI->>Nod: stop({ force? })
    Nod->>Nod: send SIGTERM or SIGKILL, remove pid file
    CLI->>Nod: restart()
    Nod->>Nod: stop() then start()
    end

    rect `#fff3e6`
    Note over CLI,Nod: Logs retrieval
    CLI->>Nod: logs(lines)
    Nod->>Child: execa tail -n lines logfile
    Child->>Nod: return log output -> CLI
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Focus areas:
    • NodemonService: detached child lifecycle, log stream handling, PID file write/cleanup, signal handling and race conditions.
    • CLI wiring: DI/provider substitutions and stop flag API change.
    • Environment and packaging: ensure nodemon paths and build steps produce the correct artifacts.
    • Tests: validate new unit/integration tests and ensure removed PM2 tests don't leave regressions.

Poem

🐇 I nudged the daemon out for nodemon light,

pid files hum and logs take flight,
children spawn and write their name,
stop and restart, the commands reclaim,
a rabbit hops — processes set right.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: swap to nodemon instead of PM2' accurately describes the primary change—replacing PM2 process management with nodemon throughout the codebase.
✨ 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 codex/switch-api-process-management-to-nodemon

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9253250 and a5e9b83.

📒 Files selected for processing (2)
  • api/src/unraid-api/cli/nodemon.service.spec.ts (1 hunks)
  • api/src/unraid-api/cli/nodemon.service.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (8)
📓 Common learnings
Learnt from: pujitm
Repo: unraid/api PR: 1367
File: packages/unraid-api-plugin-connect/src/pubsub/user.service.ts:44-52
Timestamp: 2025-04-23T20:19:42.542Z
Learning: The project uses a custom or extended implementation of NestJS ConfigService that includes a `set()` method for runtime configuration mutation, unlike the standard nestjs/config package which only provides getter methods.
📚 Learning: 2025-04-21T18:25:16.491Z
Learnt from: pujitm
Repo: unraid/api PR: 1352
File: api/src/unraid-api/cli/dependency.service.ts:114-117
Timestamp: 2025-04-21T18:25:16.491Z
Learning: Error masking through try/catch blocks is not desirable for the `npmInstall` method in `DependencyService` as errors should propagate to the caller.

Applied to files:

  • api/src/unraid-api/cli/nodemon.service.ts
📚 Learning: 2025-03-07T19:29:12.540Z
Learnt from: pujitm
Repo: unraid/api PR: 1219
File: api/src/unraid-api/main.ts:18-25
Timestamp: 2025-03-07T19:29:12.540Z
Learning: When handling type mismatches between dependencies in TypeScript (such as between NestJS and Fastify), prefer using `ts-expect-error` with a detailed explanation comment instead of `as any` type assertions. This better documents the reason for the type bypass and makes the issue more visible for future maintenance.

Applied to files:

  • api/src/unraid-api/cli/nodemon.service.ts
📚 Learning: 2025-04-21T18:25:16.491Z
Learnt from: pujitm
Repo: unraid/api PR: 1352
File: api/src/unraid-api/cli/dependency.service.ts:114-117
Timestamp: 2025-04-21T18:25:16.491Z
Learning: Methods in `DependencyService` like `npmInstall` and `rebuildVendorArchive` intentionally propagate errors from execa calls upward rather than handling them internally, allowing callers to implement appropriate error handling. This follows the pattern documented in the `rebuildVendorArchive` method's docstring.

Applied to files:

  • api/src/unraid-api/cli/nodemon.service.ts
📚 Learning: 2025-03-13T16:17:55.820Z
Learnt from: elibosley
Repo: unraid/api PR: 1211
File: api/src/unraid-api/graph/connect/connect-settings.service.ts:48-53
Timestamp: 2025-03-13T16:17:55.820Z
Learning: In NestJS services, dynamic imports should be wrapped in try/catch blocks with proper error logging and fallback handling to prevent unhandled rejections from crashing the application.

Applied to files:

  • api/src/unraid-api/cli/nodemon.service.ts
📚 Learning: 2024-11-05T14:49:07.308Z
Learnt from: elibosley
Repo: unraid/api PR: 942
File: api/src/unraid-api/auth/api-key.service.ts:62-70
Timestamp: 2024-11-05T14:49:07.308Z
Learning: In `api/src/unraid-api/auth/api-key.service.ts`, when handling read errors in the `findById` method, throw a `GraphQLError` instead of an `InternalServerErrorException`.

Applied to files:

  • api/src/unraid-api/cli/nodemon.service.ts
📚 Learning: 2025-02-06T17:25:45.397Z
Learnt from: mdatelle
Repo: unraid/api PR: 1122
File: web/package.json:16-16
Timestamp: 2025-02-06T17:25:45.397Z
Learning: The build script in web/package.json should include type-check command (`npm run type-check`) even when NODE_ENV is production, as it provides value for local builds by catching type errors before pushing to CI/CD.

Applied to files:

  • api/src/unraid-api/cli/nodemon.service.ts
📚 Learning: 2025-02-05T14:43:48.568Z
Learnt from: elibosley
Repo: unraid/api PR: 1120
File: plugin/package.json:0-0
Timestamp: 2025-02-05T14:43:48.568Z
Learning: In Node.js projects, npm scripts should be organized with clear namespacing (e.g., build:*, docker:*, env:*) and include proper environment validation and error handling. Each script should follow the single responsibility principle.

Applied to files:

  • api/src/unraid-api/cli/nodemon.service.ts
🧬 Code graph analysis (2)
api/src/unraid-api/cli/nodemon.service.spec.ts (1)
packages/unraid-shared/src/util/file.ts (1)
  • fileExists (12-15)
api/src/unraid-api/cli/nodemon.service.ts (3)
api/src/environment.ts (6)
  • PATHS_LOGS_DIR (102-103)
  • NODEMON_PID_PATH (108-108)
  • NODEMON_CONFIG_PATH (107-107)
  • UNRAID_API_CWD (109-109)
  • PATHS_LOGS_FILE (104-104)
  • NODEMON_PATH (106-106)
packages/unraid-shared/src/util/file.ts (1)
  • fileExists (12-15)
api/src/unraid-api/cli/log.service.ts (1)
  • error (65-69)
🔇 Additional comments (2)
api/src/unraid-api/cli/nodemon.service.spec.ts (1)

1-381: Comprehensive test coverage—LGTM!

The test suite thoroughly covers NodemonService behavior across all major flows:

  • Dependency setup (success and failure)
  • Start flow with multiple scenarios (happy path, failures, already running, stale PID, process discovery)
  • Stop, restart, status, and logs methods
  • Error handling and cleanup in all failure modes

The previous pipeline failure related to missing SUPPRESS_LOGS in the environment mock has been resolved (line 20).

api/src/unraid-api/cli/nodemon.service.ts (1)

1-316: Well-implemented service with comprehensive error handling—LGTM!

All previous critical issues have been successfully addressed:

  • Error propagation in ensureNodemonDependencies (lines 165-172)
  • LogStream cleanup on all failure paths (lines 229, 241, 248)
  • PID validation and post-start verification (lines 228-244)
  • Environment sanitization to filter undefined values (lines 209-212)

The service properly handles:

  • PM2-to-nodemon migration (stopPm2IfRunning)
  • Process discovery and adoption
  • Stale PID cleanup
  • Comprehensive error handling with appropriate logging

The logStream is intentionally not closed on success (verified by test expectations), which is a standard pattern for detached processes where the CLI exits quickly after spawning the daemon.


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

@elibosley elibosley changed the title Copy nodemon config into release build feat: swap to nodemon instead of PM2 Nov 20, 2025
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: 6

🧹 Nitpick comments (4)
api/scripts/build.ts (1)

10-10: Build script now correctly packages nodemon.json

Including nodemon.json in the pack directory ensures nodemon-managed deployments get the config in the release artifacts, which matches the PR goal. The getDeploymentVersion import via the @app/../scripts path is acceptable given the existing aliasing, though long‑term you may want a dedicated path alias for scripts to avoid the ../ hop.

Also applies to: 95-98

api/src/unraid-api/cli/__test__/report.command.test.ts (1)

29-34: Mocks point to the right module, but last test contains redundant scenario

  • The vi.mock('@app/core/utils/process/unraid-api-running.js', …) wiring and the reset of mockIsUnraidApiRunning in beforeEach look correct and consistent with the new process-utils location and ESM style.
  • In it('should pass correct apiRunning parameter to ApiReportService', …), the second block (Lines 153‑157) stubs mockIsUnraidApiRunning to true and asserts generateReport(true) again, which is effectively identical to the first part of the test and doesn’t add coverage. If you intended to cover a different status (e.g., false or some alternate path), consider adjusting the stub accordingly; otherwise, you can drop the redundant block to keep the test focused.

Also applies to: 53-55, 153-157

api/legacy/generated-schema-legacy.graphql (1)

1244-1271: Legacy Versions schema pm2→nodemon rename is consistent

Replacing the pm2 field with nodemon on Versions matches the rest of the nodemon migration (models, resolvers, web schema). Just ensure any consumers of the legacy schema are updated to read nodemon instead of pm2.

api/src/unraid-api/graph/resolvers/info/versions/versions.resolver.ts (1)

6-6: Nodemon version wiring into PackageVersions is correct

Using getPackageJson().dependencies?.nodemon to populate the nodemon field aligns with the new PackageVersions model and schema, and gracefully returns null if the dependency is missing.

If this resolver is called frequently, consider reading and caching getPackageJson() once at module init rather than re-reading package.json on every request.

Also applies to: 34-43

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dc9a036 and 7218273.

⛔ Files ignored due to path filters (2)
  • api/src/unraid-api/cli/generated/graphql.ts is excluded by !**/generated/**
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (32)
  • api/ecosystem.config.json (0 hunks)
  • api/generated-schema.graphql (1 hunks)
  • api/legacy/generated-schema-legacy.graphql (1 hunks)
  • api/nodemon.json (1 hunks)
  • api/package.json (1 hunks)
  • api/scripts/build.ts (2 hunks)
  • api/src/__test__/core/utils/pm2/dummy-process.js (0 hunks)
  • api/src/__test__/core/utils/pm2/unraid-api-running.integration.test.ts (0 hunks)
  • api/src/__test__/core/utils/process/unraid-api-running.integration.test.ts (1 hunks)
  • api/src/core/log.ts (1 hunks)
  • api/src/core/utils/pm2/unraid-api-running.ts (0 hunks)
  • api/src/core/utils/process/unraid-api-running.ts (1 hunks)
  • api/src/environment.ts (1 hunks)
  • api/src/unraid-api/cli/__test__/report.command.test.ts (3 hunks)
  • api/src/unraid-api/cli/cli-services.module.ts (2 hunks)
  • api/src/unraid-api/cli/cli.module.ts (2 hunks)
  • api/src/unraid-api/cli/logs.command.ts (2 hunks)
  • api/src/unraid-api/cli/nodemon.service.spec.ts (1 hunks)
  • api/src/unraid-api/cli/nodemon.service.ts (1 hunks)
  • api/src/unraid-api/cli/pm2.service.spec.ts (0 hunks)
  • api/src/unraid-api/cli/pm2.service.ts (0 hunks)
  • api/src/unraid-api/cli/report.command.ts (1 hunks)
  • api/src/unraid-api/cli/restart.command.ts (2 hunks)
  • api/src/unraid-api/cli/start.command.ts (1 hunks)
  • api/src/unraid-api/cli/status.command.ts (1 hunks)
  • api/src/unraid-api/cli/stop.command.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/info/versions/versions.model.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/info/versions/versions.resolver.ts (2 hunks)
  • api/src/unraid-api/main.ts (0 hunks)
  • web/composables/gql/graphql.ts (1 hunks)
  • web/src/composables/gql/graphql.ts (5 hunks)
  • web/src/composables/gql/index.ts (1 hunks)
💤 Files with no reviewable changes (7)
  • api/src/unraid-api/main.ts
  • api/src/unraid-api/cli/pm2.service.ts
  • api/src/test/core/utils/pm2/unraid-api-running.integration.test.ts
  • api/src/unraid-api/cli/pm2.service.spec.ts
  • api/src/core/utils/pm2/unraid-api-running.ts
  • api/src/test/core/utils/pm2/dummy-process.js
  • api/ecosystem.config.json
🧰 Additional context used
🧠 Learnings (13)
📓 Common learnings
Learnt from: mdatelle
Repo: unraid/api PR: 1106
File: unraid-ui/src/components/index.ts:2-2
Timestamp: 2025-02-04T17:21:39.710Z
Learning: The unraid-ui package is undergoing a major refactoring process, and breaking changes are expected during this transition period.
📚 Learning: 2025-03-12T13:48:14.850Z
Learnt from: pujitm
Repo: unraid/api PR: 1211
File: web/composables/gql/gql.ts:17-18
Timestamp: 2025-03-12T13:48:14.850Z
Learning: In the Unraid API project, the duplicate GraphQL query and mutation strings in gql.ts files are intentionally generated by GraphQL CodeGen tool and are necessary for the type system to function properly.

Applied to files:

  • web/src/composables/gql/index.ts
  • web/src/composables/gql/graphql.ts
📚 Learning: 2025-05-23T21:59:29.632Z
Learnt from: elibosley
Repo: unraid/api PR: 1408
File: web/components/ApiKey/PermissionCounter.vue:6-6
Timestamp: 2025-05-23T21:59:29.632Z
Learning: This codebase uses ESM (ECMAScript Modules) and requires .js extensions in import statements, even when importing from TypeScript files, as the imports refer to the compiled JavaScript output.

Applied to files:

  • web/src/composables/gql/index.ts
📚 Learning: 2024-12-11T17:20:09.604Z
Learnt from: pujitm
Repo: unraid/api PR: 978
File: web/helpers/apollo-cache/index.ts:133-157
Timestamp: 2024-12-11T17:20:09.604Z
Learning: In `web/helpers/apollo-cache/index.ts`, when updating the cache in the `cache.updateQuery` function, it's sufficient to check if `data` is present, as type checking inside `data` is handled at the GraphQL layer.

Applied to files:

  • web/src/composables/gql/index.ts
📚 Learning: 2025-09-14T14:07:28.265Z
Learnt from: elibosley
Repo: unraid/api PR: 1702
File: web/eslint.config.mjs:106-106
Timestamp: 2025-09-14T14:07:28.265Z
Learning: The unraid/api codebase specifically requires Node 20+ as a minimum version, so modern Node.js features like import.meta.dirname (available since Node v20.11.0) can be used without compatibility fallbacks.

Applied to files:

  • api/src/unraid-api/graph/resolvers/info/versions/versions.model.ts
  • api/src/core/utils/process/unraid-api-running.ts
  • api/src/unraid-api/cli/cli-services.module.ts
  • api/package.json
  • api/src/environment.ts
  • api/src/unraid-api/graph/resolvers/info/versions/versions.resolver.ts
📚 Learning: 2025-02-04T13:48:45.521Z
Learnt from: pujitm
Repo: unraid/api PR: 1104
File: api/src/unraid-api/cli/stop.command.ts:14-18
Timestamp: 2025-02-04T13:48:45.521Z
Learning: The PM2Service's `run` method automatically handles logging when `raw: true` is not set in the context argument. Explicit logging is not needed in such cases.

Applied to files:

  • api/src/unraid-api/cli/logs.command.ts
  • api/src/core/log.ts
📚 Learning: 2025-03-27T13:34:53.438Z
Learnt from: pujitm
Repo: unraid/api PR: 1252
File: api/src/environment.ts:56-56
Timestamp: 2025-03-27T13:34:53.438Z
Learning: For critical components in the Unraid API, such as retrieving version information from package.json, failing fast (allowing crashes) is preferred over graceful degradation with fallback values.

Applied to files:

  • api/src/unraid-api/cli/report.command.ts
📚 Learning: 2025-04-02T21:21:29.168Z
Learnt from: elibosley
Repo: unraid/api PR: 1308
File: unraid-ui/src/components/common/loading/Error.vue:2-2
Timestamp: 2025-04-02T21:21:29.168Z
Learning: Components in the unraid-ui folder require explicit imports and are not autoloaded, unlike other parts of the project that may use Nuxt.js autoloading features.

Applied to files:

  • api/src/unraid-api/cli/cli-services.module.ts
📚 Learning: 2025-08-09T01:03:29.676Z
Learnt from: elibosley
Repo: unraid/api PR: 1575
File: packages/unraid-shared/src/services/socket-config.service.spec.ts:10-13
Timestamp: 2025-08-09T01:03:29.676Z
Learning: Vitest is used for all testing across all repositories in the unraid organization, not Jest. Always use `vi` for mocking utilities, not `jest`.

Applied to files:

  • api/src/__test__/core/utils/process/unraid-api-running.integration.test.ts
  • api/src/unraid-api/cli/__test__/report.command.test.ts
  • api/src/unraid-api/cli/nodemon.service.spec.ts
📚 Learning: 2025-03-04T14:55:00.903Z
Learnt from: elibosley
Repo: unraid/api PR: 1151
File: plugin/builder/utils/consts.ts:6-6
Timestamp: 2025-03-04T14:55:00.903Z
Learning: The startingDir constant in plugin/builder/utils/consts.ts is defined using process.cwd(), which can cause issues if directory changes occur after importing this constant. Using __dirname.split('/builder')[0] would make it more reliable by making it relative to the file location rather than the current working directory.

Applied to files:

  • api/src/environment.ts
📚 Learning: 2025-03-26T15:18:27.452Z
Learnt from: pujitm
Repo: unraid/api PR: 1252
File: plugin/docker-compose.yml:15-15
Timestamp: 2025-03-26T15:18:27.452Z
Learning: The files in the `api/deploy` directory (including `packed-pnpm-store.txz`) are gitignored build artifacts that are generated when the API is built. Building the API is a prerequisite before using the plugin builder container, as it needs access to these artifacts.

Applied to files:

  • api/scripts/build.ts
📚 Learning: 2025-02-06T17:25:45.397Z
Learnt from: mdatelle
Repo: unraid/api PR: 1122
File: web/package.json:16-16
Timestamp: 2025-02-06T17:25:45.397Z
Learning: The build script in web/package.json should include type-check command (`npm run type-check`) even when NODE_ENV is production, as it provides value for local builds by catching type errors before pushing to CI/CD.

Applied to files:

  • api/scripts/build.ts
📚 Learning: 2025-02-04T16:42:21.782Z
Learnt from: elibosley
Repo: unraid/api PR: 1105
File: api/scripts/build.mjs:0-0
Timestamp: 2025-02-04T16:42:21.782Z
Learning: In Node.js build scripts, avoid manually copying node_modules as a cache layer. Instead, rely on npm's built-in caching mechanism and use direct `npm install` commands, as this ensures dependency consistency and proper version resolution while still maintaining good performance through npm's cache.

Applied to files:

  • api/scripts/build.ts
🧬 Code graph analysis (13)
api/src/unraid-api/cli/logs.command.ts (4)
api/src/unraid-api/cli/restart.command.ts (1)
  • Command (21-54)
api/src/unraid-api/cli/start.command.ts (1)
  • Command (11-33)
api/src/unraid-api/cli/status.command.ts (1)
  • Command (5-13)
api/src/unraid-api/cli/stop.command.ts (1)
  • Command (8-28)
api/src/unraid-api/cli/status.command.ts (4)
api/src/unraid-api/cli/logs.command.ts (1)
  • Command (9-25)
api/src/unraid-api/cli/restart.command.ts (1)
  • Command (21-54)
api/src/unraid-api/cli/start.command.ts (1)
  • Command (11-33)
api/src/unraid-api/cli/stop.command.ts (1)
  • Command (8-28)
api/src/core/utils/process/unraid-api-running.ts (2)
packages/unraid-shared/src/util/file.ts (1)
  • fileExists (12-15)
api/src/environment.ts (1)
  • NODEMON_PID_PATH (114-114)
api/src/unraid-api/cli/report.command.ts (1)
api/src/core/utils/process/unraid-api-running.ts (1)
  • isUnraidApiRunning (6-23)
web/src/composables/gql/graphql.ts (1)
web/composables/gql/graphql.ts (2)
  • Node (1357-1359)
  • Scalars (11-75)
web/composables/gql/graphql.ts (1)
web/src/composables/gql/graphql.ts (2)
  • Maybe (3-3)
  • Scalars (11-75)
api/src/__test__/core/utils/process/unraid-api-running.integration.test.ts (1)
api/src/core/utils/process/unraid-api-running.ts (1)
  • isUnraidApiRunning (6-23)
api/src/unraid-api/cli/start.command.ts (4)
api/src/unraid-api/cli/logs.command.ts (1)
  • Command (9-25)
api/src/unraid-api/cli/restart.command.ts (2)
  • Command (21-54)
  • LogLevelOptions (9-11)
api/src/unraid-api/cli/status.command.ts (1)
  • Command (5-13)
api/src/unraid-api/cli/stop.command.ts (1)
  • Command (8-28)
api/src/unraid-api/cli/nodemon.service.ts (3)
api/src/environment.ts (6)
  • PATHS_LOGS_DIR (101-102)
  • NODEMON_PID_PATH (114-114)
  • PATHS_LOGS_FILE (103-103)
  • NODEMON_PATH (105-112)
  • NODEMON_CONFIG_PATH (113-113)
  • UNRAID_API_CWD (115-115)
api/src/unraid-api/cli/log.service.ts (1)
  • error (65-69)
packages/unraid-shared/src/util/file.ts (1)
  • fileExists (12-15)
api/src/core/log.ts (1)
api/src/environment.ts (2)
  • SUPPRESS_LOGS (94-94)
  • LOG_TYPE (88-88)
api/src/unraid-api/cli/stop.command.ts (4)
api/src/unraid-api/cli/logs.command.ts (1)
  • Command (9-25)
api/src/unraid-api/cli/restart.command.ts (1)
  • Command (21-54)
api/src/unraid-api/cli/start.command.ts (1)
  • Command (11-33)
api/src/unraid-api/cli/status.command.ts (1)
  • Command (5-13)
api/src/unraid-api/cli/nodemon.service.spec.ts (1)
packages/unraid-shared/src/util/file.ts (1)
  • fileExists (12-15)
api/src/unraid-api/graph/resolvers/info/versions/versions.resolver.ts (1)
api/src/environment.ts (1)
  • getPackageJson (49-53)
🪛 GitHub Actions: CI - Main (API)
api/src/unraid-api/cli/nodemon.service.spec.ts

[error] 1-1: vitest error: No 'SUPPRESS_LOGS' export is defined on the '@app/environment.js' mock in nodemon.service.spec.ts. Ensure environment mock exports SUPPRESS_LOGS.

🔇 Additional comments (18)
web/src/composables/gql/index.ts (1)

1-2: ESM re-exports are consistent and correct

The barrel re-exports look good and align with the existing ESM/import style in this repo; no changes needed. Based on learnings.

api/src/core/log.ts (1)

20-29: Updated logging comments accurately describe behavior

The revised comments now correctly describe that output goes directly to a log file and why colorization is disabled; they match the existing colorize: false/destination: logDestination configuration without changing behavior.

api/package.json (1)

140-140: Nodemon 3.1.10 is secure and appropriate for runtime deployment

Verification confirms no npm security advisories affecting version 3.1.10. The latest stable release is 3.1.11, but Renovate will handle future updates automatically. The move to dependencies aligns with your new process manager strategy.

api/nodemon.json (1)

1-18: Nodemon config looks sound and matches build layout

Watching dist/main.js and myservers.cfg, ignoring node_modules/src/.env.*, and executing node ./dist/main.js with NODE_ENV=production all look consistent with the packaged API. No changes needed.

api/src/unraid-api/cli/report.command.ts (1)

33-40: Dynamic import and log message now correctly reference nodemon-based check

Importing @app/core/utils/process/unraid-api-running.js and updating the debug message to "failed to check nodemon state" cleanly rewire the report command onto the new process-based liveness check without altering behavior.

web/composables/gql/graphql.ts (1)

1511-1528: Frontend PackageVersions type correctly adds nodemon

Adding the nullable nodemon?: Maybe<Scalars['String']['output']> field with the corresponding docstring keeps the web GraphQL typings in sync with the server schema and versions resolver.

api/generated-schema.graphql (1)

1666-1690: Generated schema PackageVersions now exposes nodemon

The """nodemon version""" docstring and nodemon: String field correctly reflect the server-side change and stay consistent with the TS model and client typings. No issues here as long as this file continues to be generated from the updated schema sources.

api/src/unraid-api/graph/resolvers/info/versions/versions.model.ts (1)

17-42: PackageVersions model nodemon field matches schema & resolver

Adding the nullable nodemon field with the proper description keeps the GraphQL model in sync with both the generated schema and VersionsResolver.packages(). Looks good.

api/src/unraid-api/cli/cli.module.ts (1)

16-16: LGTM! Clean service replacement.

The NodemonService import and provider registration are correctly implemented, aligning with the PM2-to-Nodemon migration strategy.

Also applies to: 67-67

api/src/unraid-api/cli/restart.command.ts (1)

5-7: LGTM! Restart command correctly migrated to Nodemon.

The service replacement is consistent with the broader migration, and the log level uppercasing aligns with environment variable conventions.

Also applies to: 23-35

api/src/unraid-api/cli/cli-services.module.ts (1)

7-7: LGTM! Service wiring correctly updated.

The NodemonService replacement in the CLI services module is consistent with the migration pattern.

Also applies to: 24-24

api/src/unraid-api/cli/nodemon.service.spec.ts (1)

49-98: Well-structured test suite.

The test cases properly cover key NodemonService functionality with appropriate mocking and lifecycle management. Good use of Vitest patterns.

api/src/unraid-api/cli/status.command.ts (1)

3-3: LGTM! Status command correctly migrated.

The service replacement follows the same clean pattern as other commands in this migration.

Also applies to: 7-7, 11-11

api/src/__test__/core/utils/process/unraid-api-running.integration.test.ts (1)

7-53: LGTM! Comprehensive integration test with proper lifecycle management.

The test suite covers all critical scenarios (missing pid file, live pid, invalid pid) with appropriate setup/teardown and dynamic module mocking. Good use of Vitest patterns.

api/src/unraid-api/cli/logs.command.ts (1)

3-3: LGTM! Logs command successfully migrated.

The NodemonService integration is clean and consistent with the rest of the migration.

Also applies to: 11-11, 23-23

api/src/unraid-api/cli/stop.command.ts (1)

1-28: LGTM!

The migration from PM2Service to NodemonService is clean and well-structured. The semantic change from the --delete flag to --force is appropriate—in the PM2 context, "delete" removed the process from PM2's process list, whereas in the Nodemon context, "force" appropriately indicates using SIGKILL instead of SIGTERM for process termination.

web/src/composables/gql/graphql.ts (1)

562-571: Auto-generated GraphQL types reflect schema changes correctly.

These changes are auto-generated by GraphQL CodeGen and correctly reflect the backend schema migration from PM2 to Nodemon. The nodemon field now replaces pm2 in PackageVersions, and the new CpuPackages type with telemetry support has been added.

Based on learnings.

Also applies to: 883-883, 900-901, 1548-1549, 2070-2070

api/src/unraid-api/cli/start.command.ts (1)

1-33: LGTM! Clean migration to Nodemon.

The PM2-based startup flow with its lifecycle management has been cleanly replaced with a simple delegation to NodemonService.start(). The log level configuration is properly preserved and passed through environment variables. This simplification removes complexity while maintaining the same functionality.

@codecov
Copy link

codecov bot commented Nov 20, 2025

Codecov Report

❌ Patch coverage is 53.50318% with 146 lines in your changes missing coverage. Please review.
✅ Project coverage is 52.19%. Comparing base (31af99e) to head (a5e9b83).

Files with missing lines Patch % Lines
api/src/unraid-api/cli/nodemon.service.ts 53.17% 118 Missing ⚠️
api/src/unraid-api/cli/stop.command.ts 0.00% 7 Missing ⚠️
api/src/unraid-api/cli/restart.command.ts 33.33% 4 Missing ⚠️
api/src/unraid-api/cli/start.command.ts 0.00% 4 Missing ⚠️
api/src/unraid-api/cli/logs.command.ts 0.00% 3 Missing ⚠️
api/src/unraid-api/cli/status.command.ts 0.00% 3 Missing ⚠️
api/src/core/utils/process/unraid-api-running.ts 89.47% 2 Missing ⚠️
api/src/unraid-api/cli/cli.module.ts 0.00% 2 Missing ⚠️
api/src/unraid-api/cli/report.command.ts 50.00% 1 Missing ⚠️
...pi/graph/resolvers/info/versions/versions.model.ts 50.00% 1 Missing ⚠️
... and 1 more
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1798      +/-   ##
==========================================
+ Coverage   52.04%   52.19%   +0.15%     
==========================================
  Files         874      873       -1     
  Lines       50372    50460      +88     
  Branches     5017     5050      +33     
==========================================
+ Hits        26214    26337     +123     
+ Misses      24083    24048      -35     
  Partials       75       75              

☔ 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.

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: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
api/src/core/log.ts (1)

119-132: Arrays in sanitizeParams can leak sensitive values

sanitizeParams recurses only into plain objects and skips arrays, so something like { users: [{ password: 'x' }] } will log the raw password. Given this is core logging, this is a non-trivial privacy/security risk.

Consider extending masking to arrays of objects, e.g. by mapping over arrays and calling sanitizeParams on object elements before logging.

🧹 Nitpick comments (9)
api/src/core/log.ts (2)

20-21: Clarify environment assumptions for disabling color and consider configurability

The comment and colorize: false / colorizeObjects: false enforce non-colored pretty output in all contexts, not only when logs are truly being redirected to a file. If you expect interactive/dev runs where stdout is a TTY, you might want a config flag (e.g., LOG_COLORIZE) or a TTY check to re-enable color there, while keeping it off for file-piped production output.

Also applies to: 25-32


18-19: Normalize SUPPRESS_LOGS handling to the imported constant

logDestination checks process.env.SUPPRESS_LOGS === 'true' directly while stream uses the imported SUPPRESS_LOGS flag. This duplication is easy to forget if env parsing changes and can also diverge if process.env is mutated at runtime. Prefer routing both through SUPPRESS_LOGS for a single source of truth.

Also applies to: 22-24

api/src/environment.ts (1)

105-116: Nodemon path/env constants look correct; ensure PID directory exists

The NODEMON_PATH, NODEMON_CONFIG_PATH, and UNRAID_API_CWD calculations from import.meta.dirname and ../../ look consistent with both the monorepo layout and the packed dist + node_modules release layout. With Node 20+ and import.meta.dirname this should be robust.

One thing to confirm: NODEMON_PID_PATH defaults to /var/run/unraid-api/nodemon.pid. Make sure whatever writes the PID file creates the /var/run/unraid-api directory (or its configured parent) before writing, otherwise you’ll get ENOENT on first write on a clean system.

Based on learnings.

api/scripts/build.ts (1)

10-10: Alias import for getDeploymentVersion is a bit subtle; consider simplifying

Using @app/../scripts/get-deployment-version.js ties this script to the @app/* path mapping and relies on the loader rewriting it to something like ./src/../scripts/get-deployment-version.js. That’s a bit non-obvious for future readers and could break if the alias ever changes.

Unless there’s a specific reason to route this through @app, consider reverting to a plain relative import from the same directory, which is loader‑agnostic:

-import { getDeploymentVersion } from '@app/../scripts/get-deployment-version.js';
+import { getDeploymentVersion } from './get-deployment-version.js';

In any case, please run the build script (pnpm --filter @unraid/api build:release) on a clean checkout to confirm this alias-based import resolves as expected.

api/src/unraid-api/graph/resolvers/info/versions/versions.resolver.ts (1)

38-38: Consider whether to return the dependency version range or the actual installed version.

The current implementation returns getPackageJson().dependencies?.nodemon, which may include a version range (e.g., ^3.0.0 or ~3.1.4) rather than the actual installed version. This is consistent with how dependency information is typically stored in package.json, but differs from other version fields that return actual running versions (e.g., softwareVersions.node returns the runtime version like 20.11.0).

If you want to display the exact installed version, consider using nodemon --version or reading from node_modules/nodemon/package.json.

api/src/unraid-api/cli/nodemon.service.ts (3)

45-50: Handle PID file races and read errors more defensively

getStoredPid does an existence check then readFile, which can still throw (e.g. if the file is removed between the two calls or unreadable). Right now any such error would bubble up into stop / status.

Consider collapsing this into a single readFile with a catch and treating failures as “no PID”, e.g.:

private async getStoredPid(): Promise<number | null> {
    try {
        const contents = (await readFile(NODEMON_PID_PATH, 'utf-8')).trim();
        const pid = Number.parseInt(contents, 10);
        return Number.isNaN(pid) ? null : pid;
    } catch {
        return null;
    }
}

This makes stop/status resilient to transient file races or permissions issues.


87-105: Be cautious about removing PID file when kill fails

stop always deletes the PID file in the finally block, even if process.kill throws for reasons other than “no such process” (e.g. permission issues). That can leave a still-running nodemon process without a PID file, making later status/stop operations think nothing is running.

If you care about this edge case, consider:

  • Only removing the PID file when kill succeeds or isPidRunning(pid) returns false, or
  • Logging more explicitly when you remove the PID file after a failed kill so operators can track potential strays.

Not a blocker, but worth considering for robustness.


129-132: Logs command behavior is reasonable; consider friendlier error handling

Using execa('tail', ['-n', ${lines}, PATHS_LOGS_FILE]) is straightforward and leverages the system tail. If you expect this to run on systems where tail or the log file might be missing, optionally wrap this in try/catch and translate failures into a clearer message like “No logs available yet” instead of surfacing a raw execa error.

api/src/unraid-api/cli/start.command.ts (1)

20-32: Harden run error handling and normalize LOG_LEVEL env

Verification confirms that @Option defaultValue does not guarantee the property will be set in all invocation paths (e.g., programmatic calls bypassing commander parsing), so your concern about options.logLevel being undefined is valid.

Two improvements are recommended:

  • Wrap the call in a try/catch like RestartCommand.run so CLI failures are logged cleanly and exit with a non‑zero code.
  • Normalize/fallback the env value so LOG_LEVEL is always a string:
async run(_: string[], options: LogLevelOptions): Promise<void> {
    this.logger.info('Starting the Unraid API');
    const logLevel = (options.logLevel ?? LOG_LEVEL).toUpperCase();
    try {
        await this.nodemon.start({ env: { LOG_LEVEL: logLevel } });
    } catch (error) {
        if (error instanceof Error) {
            this.logger.error(error.message);
        } else {
            this.logger.error('Unknown error occurred');
        }
        process.exit(1);
    }
}

This keeps behavior consistent with restart and avoids passing an undefined env value to execa.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dc9a036 and f2ee4ba.

⛔ Files ignored due to path filters (2)
  • api/src/unraid-api/cli/generated/graphql.ts is excluded by !**/generated/**
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (33)
  • api/ecosystem.config.json (0 hunks)
  • api/generated-schema.graphql (1 hunks)
  • api/legacy/generated-schema-legacy.graphql (1 hunks)
  • api/nodemon.json (1 hunks)
  • api/package.json (1 hunks)
  • api/scripts/build.ts (2 hunks)
  • api/src/__test__/core/utils/pm2/dummy-process.js (0 hunks)
  • api/src/__test__/core/utils/pm2/unraid-api-running.integration.test.ts (0 hunks)
  • api/src/__test__/core/utils/process/unraid-api-running.integration.test.ts (1 hunks)
  • api/src/__test__/graphql/resolvers/rclone-api.service.test.ts (1 hunks)
  • api/src/core/log.ts (1 hunks)
  • api/src/core/utils/pm2/unraid-api-running.ts (0 hunks)
  • api/src/core/utils/process/unraid-api-running.ts (1 hunks)
  • api/src/environment.ts (1 hunks)
  • api/src/unraid-api/cli/__test__/report.command.test.ts (3 hunks)
  • api/src/unraid-api/cli/cli-services.module.ts (2 hunks)
  • api/src/unraid-api/cli/cli.module.ts (2 hunks)
  • api/src/unraid-api/cli/logs.command.ts (2 hunks)
  • api/src/unraid-api/cli/nodemon.service.spec.ts (1 hunks)
  • api/src/unraid-api/cli/nodemon.service.ts (1 hunks)
  • api/src/unraid-api/cli/pm2.service.spec.ts (0 hunks)
  • api/src/unraid-api/cli/pm2.service.ts (0 hunks)
  • api/src/unraid-api/cli/report.command.ts (1 hunks)
  • api/src/unraid-api/cli/restart.command.ts (2 hunks)
  • api/src/unraid-api/cli/start.command.ts (1 hunks)
  • api/src/unraid-api/cli/status.command.ts (1 hunks)
  • api/src/unraid-api/cli/stop.command.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/info/versions/versions.model.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/info/versions/versions.resolver.ts (2 hunks)
  • api/src/unraid-api/main.ts (0 hunks)
  • web/composables/gql/graphql.ts (1 hunks)
  • web/src/composables/gql/graphql.ts (5 hunks)
  • web/src/composables/gql/index.ts (1 hunks)
💤 Files with no reviewable changes (7)
  • api/src/unraid-api/main.ts
  • api/src/unraid-api/cli/pm2.service.spec.ts
  • api/src/core/utils/pm2/unraid-api-running.ts
  • api/src/unraid-api/cli/pm2.service.ts
  • api/src/test/core/utils/pm2/dummy-process.js
  • api/src/test/core/utils/pm2/unraid-api-running.integration.test.ts
  • api/ecosystem.config.json
🧰 Additional context used
🧠 Learnings (15)
📚 Learning: 2025-09-14T14:07:28.265Z
Learnt from: elibosley
Repo: unraid/api PR: 1702
File: web/eslint.config.mjs:106-106
Timestamp: 2025-09-14T14:07:28.265Z
Learning: The unraid/api codebase specifically requires Node 20+ as a minimum version, so modern Node.js features like import.meta.dirname (available since Node v20.11.0) can be used without compatibility fallbacks.

Applied to files:

  • api/src/core/utils/process/unraid-api-running.ts
  • api/src/unraid-api/cli/report.command.ts
  • api/src/environment.ts
  • api/src/unraid-api/graph/resolvers/info/versions/versions.resolver.ts
  • api/src/unraid-api/cli/cli-services.module.ts
  • api/package.json
📚 Learning: 2025-01-27T14:57:46.617Z
Learnt from: elibosley
Repo: unraid/api PR: 1063
File: web/_data/serverState.ts:137-147
Timestamp: 2025-01-27T14:57:46.617Z
Learning: The values in `web/_data/serverState.ts` are used for testing purposes and should remain as hardcoded mock data to facilitate testing different scenarios.

Applied to files:

  • api/src/__test__/graphql/resolvers/rclone-api.service.test.ts
📚 Learning: 2025-02-03T18:57:28.442Z
Learnt from: elibosley
Repo: unraid/api PR: 1101
File: api/src/unraid-api/unraid-file-modifier/modifications/__test__/generic-modification.spec.ts:55-56
Timestamp: 2025-02-03T18:57:28.442Z
Learning: Using console.log is acceptable in test files, especially for debugging test execution. The logger instances in test files are often used as mocks/dependencies for the classes being tested, not for actual logging.

Applied to files:

  • api/src/__test__/graphql/resolvers/rclone-api.service.test.ts
📚 Learning: 2025-03-27T13:34:53.438Z
Learnt from: pujitm
Repo: unraid/api PR: 1252
File: api/src/environment.ts:56-56
Timestamp: 2025-03-27T13:34:53.438Z
Learning: For critical components in the Unraid API, such as retrieving version information from package.json, failing fast (allowing crashes) is preferred over graceful degradation with fallback values.

Applied to files:

  • api/src/unraid-api/cli/report.command.ts
📚 Learning: 2025-08-09T01:03:29.676Z
Learnt from: elibosley
Repo: unraid/api PR: 1575
File: packages/unraid-shared/src/services/socket-config.service.spec.ts:10-13
Timestamp: 2025-08-09T01:03:29.676Z
Learning: Vitest is used for all testing across all repositories in the unraid organization, not Jest. Always use `vi` for mocking utilities, not `jest`.

Applied to files:

  • api/src/__test__/core/utils/process/unraid-api-running.integration.test.ts
  • api/src/unraid-api/cli/nodemon.service.spec.ts
  • api/src/unraid-api/cli/__test__/report.command.test.ts
📚 Learning: 2025-03-04T14:55:00.903Z
Learnt from: elibosley
Repo: unraid/api PR: 1151
File: plugin/builder/utils/consts.ts:6-6
Timestamp: 2025-03-04T14:55:00.903Z
Learning: The startingDir constant in plugin/builder/utils/consts.ts is defined using process.cwd(), which can cause issues if directory changes occur after importing this constant. Using __dirname.split('/builder')[0] would make it more reliable by making it relative to the file location rather than the current working directory.

Applied to files:

  • api/src/environment.ts
📚 Learning: 2025-03-12T13:48:14.850Z
Learnt from: pujitm
Repo: unraid/api PR: 1211
File: web/composables/gql/gql.ts:17-18
Timestamp: 2025-03-12T13:48:14.850Z
Learning: In the Unraid API project, the duplicate GraphQL query and mutation strings in gql.ts files are intentionally generated by GraphQL CodeGen tool and are necessary for the type system to function properly.

Applied to files:

  • web/composables/gql/graphql.ts
  • web/src/composables/gql/index.ts
📚 Learning: 2025-02-06T17:25:45.397Z
Learnt from: mdatelle
Repo: unraid/api PR: 1122
File: web/package.json:16-16
Timestamp: 2025-02-06T17:25:45.397Z
Learning: The build script in web/package.json should include type-check command (`npm run type-check`) even when NODE_ENV is production, as it provides value for local builds by catching type errors before pushing to CI/CD.

Applied to files:

  • api/scripts/build.ts
📚 Learning: 2025-03-26T15:18:27.452Z
Learnt from: pujitm
Repo: unraid/api PR: 1252
File: plugin/docker-compose.yml:15-15
Timestamp: 2025-03-26T15:18:27.452Z
Learning: The files in the `api/deploy` directory (including `packed-pnpm-store.txz`) are gitignored build artifacts that are generated when the API is built. Building the API is a prerequisite before using the plugin builder container, as it needs access to these artifacts.

Applied to files:

  • api/scripts/build.ts
📚 Learning: 2025-02-04T16:42:21.782Z
Learnt from: elibosley
Repo: unraid/api PR: 1105
File: api/scripts/build.mjs:0-0
Timestamp: 2025-02-04T16:42:21.782Z
Learning: In Node.js build scripts, avoid manually copying node_modules as a cache layer. Instead, rely on npm's built-in caching mechanism and use direct `npm install` commands, as this ensures dependency consistency and proper version resolution while still maintaining good performance through npm's cache.

Applied to files:

  • api/scripts/build.ts
📚 Learning: 2025-04-02T21:21:29.168Z
Learnt from: elibosley
Repo: unraid/api PR: 1308
File: unraid-ui/src/components/common/loading/Error.vue:2-2
Timestamp: 2025-04-02T21:21:29.168Z
Learning: Components in the unraid-ui folder require explicit imports and are not autoloaded, unlike other parts of the project that may use Nuxt.js autoloading features.

Applied to files:

  • api/src/unraid-api/cli/cli-services.module.ts
📚 Learning: 2025-05-23T21:59:29.632Z
Learnt from: elibosley
Repo: unraid/api PR: 1408
File: web/components/ApiKey/PermissionCounter.vue:6-6
Timestamp: 2025-05-23T21:59:29.632Z
Learning: This codebase uses ESM (ECMAScript Modules) and requires .js extensions in import statements, even when importing from TypeScript files, as the imports refer to the compiled JavaScript output.

Applied to files:

  • web/src/composables/gql/index.ts
📚 Learning: 2024-12-11T17:20:09.604Z
Learnt from: pujitm
Repo: unraid/api PR: 978
File: web/helpers/apollo-cache/index.ts:133-157
Timestamp: 2024-12-11T17:20:09.604Z
Learning: In `web/helpers/apollo-cache/index.ts`, when updating the cache in the `cache.updateQuery` function, it's sufficient to check if `data` is present, as type checking inside `data` is handled at the GraphQL layer.

Applied to files:

  • web/src/composables/gql/index.ts
📚 Learning: 2025-03-12T13:35:43.900Z
Learnt from: pujitm
Repo: unraid/api PR: 1211
File: web/codegen.ts:14-14
Timestamp: 2025-03-12T13:35:43.900Z
Learning: The JSON scalar type in web/codegen.ts was temporarily changed from 'string' to 'any' for compatibility with JsonForms integration. This change facilitates the implementation of the Connect settings web component.

Applied to files:

  • web/src/composables/gql/index.ts
📚 Learning: 2025-02-04T13:48:45.521Z
Learnt from: pujitm
Repo: unraid/api PR: 1104
File: api/src/unraid-api/cli/stop.command.ts:14-18
Timestamp: 2025-02-04T13:48:45.521Z
Learning: The PM2Service's `run` method automatically handles logging when `raw: true` is not set in the context argument. Explicit logging is not needed in such cases.

Applied to files:

  • api/src/unraid-api/cli/logs.command.ts
🧬 Code graph analysis (13)
api/src/core/utils/process/unraid-api-running.ts (2)
packages/unraid-shared/src/util/file.ts (1)
  • fileExists (12-15)
api/src/environment.ts (1)
  • NODEMON_PID_PATH (114-114)
api/src/unraid-api/cli/report.command.ts (1)
api/src/core/utils/process/unraid-api-running.ts (1)
  • isUnraidApiRunning (6-23)
api/src/__test__/core/utils/process/unraid-api-running.integration.test.ts (1)
api/src/core/utils/process/unraid-api-running.ts (1)
  • isUnraidApiRunning (6-23)
api/src/unraid-api/graph/resolvers/info/versions/versions.resolver.ts (1)
api/src/environment.ts (1)
  • getPackageJson (49-53)
api/src/unraid-api/cli/nodemon.service.spec.ts (1)
packages/unraid-shared/src/util/file.ts (1)
  • fileExists (12-15)
web/composables/gql/graphql.ts (1)
web/src/composables/gql/graphql.ts (2)
  • Maybe (3-3)
  • Scalars (11-75)
api/src/unraid-api/cli/status.command.ts (4)
api/src/unraid-api/cli/logs.command.ts (1)
  • Command (9-25)
api/src/unraid-api/cli/restart.command.ts (1)
  • Command (21-54)
api/src/unraid-api/cli/start.command.ts (1)
  • Command (11-33)
api/src/unraid-api/cli/stop.command.ts (1)
  • Command (8-28)
api/src/unraid-api/cli/stop.command.ts (4)
api/src/unraid-api/cli/logs.command.ts (1)
  • Command (9-25)
api/src/unraid-api/cli/restart.command.ts (1)
  • Command (21-54)
api/src/unraid-api/cli/start.command.ts (1)
  • Command (11-33)
api/src/unraid-api/cli/status.command.ts (1)
  • Command (5-13)
api/src/unraid-api/cli/logs.command.ts (4)
api/src/unraid-api/cli/restart.command.ts (1)
  • Command (21-54)
api/src/unraid-api/cli/start.command.ts (1)
  • Command (11-33)
api/src/unraid-api/cli/status.command.ts (1)
  • Command (5-13)
api/src/unraid-api/cli/stop.command.ts (1)
  • Command (8-28)
api/src/core/log.ts (1)
api/src/environment.ts (2)
  • SUPPRESS_LOGS (94-94)
  • LOG_TYPE (88-88)
api/src/unraid-api/cli/nodemon.service.ts (3)
api/src/environment.ts (6)
  • PATHS_LOGS_DIR (101-102)
  • NODEMON_PID_PATH (114-114)
  • PATHS_LOGS_FILE (103-103)
  • NODEMON_PATH (105-112)
  • NODEMON_CONFIG_PATH (113-113)
  • UNRAID_API_CWD (115-115)
api/src/unraid-api/cli/log.service.ts (1)
  • error (65-69)
packages/unraid-shared/src/util/file.ts (1)
  • fileExists (12-15)
api/src/unraid-api/cli/start.command.ts (4)
api/src/unraid-api/cli/logs.command.ts (1)
  • Command (9-25)
api/src/unraid-api/cli/restart.command.ts (2)
  • Command (21-54)
  • LogLevelOptions (9-11)
api/src/unraid-api/cli/status.command.ts (1)
  • Command (5-13)
api/src/unraid-api/cli/stop.command.ts (1)
  • Command (8-28)
web/src/composables/gql/graphql.ts (2)
api/src/unraid-api/cli/generated/graphql.ts (4)
  • CpuPackages (562-571)
  • Node (1385-1387)
  • Scalars (11-75)
  • Maybe (3-3)
web/composables/gql/graphql.ts (3)
  • Node (1357-1359)
  • Scalars (11-75)
  • Maybe (3-3)
🔇 Additional comments (26)
api/src/__test__/graphql/resolvers/rclone-api.service.test.ts (1)

54-55: LGTM! Environment mock standardization.

The addition of SUPPRESS_LOGS and LOG_LEVEL to the environment mock aligns with the broader PM2-to-nodemon migration and standardizes the test configuration. Since the Logger is already mocked at lines 65-76, these additions don't affect test behavior but provide consistency with other test files.

api/package.json (1)

140-140: Confirm nodemon is intended as a runtime dependency

Adding nodemon to dependencies makes sense if deployments rely on it as the process manager (mirroring how PM2 was treated). Just double‑check there are no usage contexts where @unraid/api is consumed purely as a library and this heavier runtime dependency would be undesirable, and that release builds indeed need nodemon available at runtime.

api/scripts/build.ts (1)

97-97: Including nodemon.json in the release pack matches nodemon-managed deployments

Updating the pack step to cp -r dist README.md .env.* nodemon.json ./deploy/pack/ ensures the nodemon configuration is shipped with the release, which aligns with switching process management from PM2 to nodemon.

Just confirm that api/nodemon.json is always present in the repo (and in any CI/build contexts), since a missing file here will now cause the build to fail at the copy step.

web/src/composables/gql/index.ts (1)

1-2: Stylistic quote change only; exports remain the same

Only the quote style changed here; the exported modules and paths are unchanged, so there’s no behavioral impact.

api/legacy/generated-schema-legacy.graphql (1)

1260-1260: Renaming Versions.pm2 → Versions.nodemon is a schema-breaking change

Updating the Versions type to expose nodemon: String instead of pm2 aligns with the runtime change, but it is a breaking change for any clients that still query pm2 against the legacy schema.

If all consumers (including anything relying on this “legacy” schema) are updated in lockstep with this PR, this is fine. Otherwise, consider temporarily exposing both fields, or at least coordinating a versioned rollout so older clients don’t start failing GraphQL queries unexpectedly.

api/src/unraid-api/cli/report.command.ts (1)

36-40: LGTM!

The import path and error message have been correctly updated to reflect the migration from PM2 to nodemon-based process management.

api/src/core/utils/process/unraid-api-running.ts (1)

6-23: LGTM!

The implementation correctly checks if the Unraid API process is running by:

  1. Verifying the PID file exists
  2. Reading and validating the PID
  3. Using process.kill(pid, 0) to check process liveness without sending a signal

This is a standard and reliable approach for process health checking.

api/generated-schema.graphql (1)

1676-1677: LGTM!

The GraphQL schema has been correctly updated to replace the pm2 field with nodemon in the PackageVersions type. This is an auto-generated file that reflects the changes in the underlying model.

api/src/unraid-api/cli/__test__/report.command.test.ts (1)

29-34: LGTM!

The test mocks have been correctly updated to reference the new process-based utility instead of PM2-specific code.

api/src/unraid-api/cli/cli-services.module.ts (2)

7-7: LGTM!

The import has been correctly updated to use NodemonService instead of PM2Service, aligning with the broader migration to nodemon-based process management.


24-24: LGTM!

The providers array has been correctly updated to register NodemonService instead of PM2Service.

api/src/unraid-api/graph/resolvers/info/versions/versions.model.ts (1)

28-29: LGTM!

The model has been correctly updated to replace the pm2 field with nodemon, consistent with the broader migration to nodemon-based process management.

api/src/unraid-api/graph/resolvers/info/versions/versions.resolver.ts (1)

6-6: LGTM!

The import of getPackageJson is correctly added to support retrieving the nodemon version from package.json.

api/src/__test__/core/utils/process/unraid-api-running.integration.test.ts (1)

7-54: Excellent test coverage for nodemon PID detection.

The integration test is well-structured with proper setup/teardown lifecycle management and covers the key scenarios (missing file, valid PID, invalid PID). The use of dynamic imports with mocking ensures proper isolation between test cases.

api/src/unraid-api/cli/nodemon.service.spec.ts (1)

29-101: Comprehensive unit tests for NodemonService.

The test suite provides excellent coverage of the service's key functionality: dependency setup, process starting, and status checking. The mocking strategy effectively isolates the service behavior, and the assertions verify all critical interactions with the filesystem and process management.

api/src/unraid-api/cli/status.command.ts (1)

3-11: Clean migration to NodemonService.

The status command has been successfully migrated from PM2 to nodemon with a simplified implementation. The changes are consistent with the broader migration pattern across all CLI commands.

api/src/unraid-api/cli/logs.command.ts (1)

3-23: Successful migration to NodemonService.

The logs command has been cleanly migrated to use NodemonService while maintaining the same functionality for viewing logs with configurable line counts.

web/composables/gql/graphql.ts (1)

1526-1527: GraphQL types updated to reflect nodemon migration.

The generated types correctly reflect the schema change from pm2 to nodemon version tracking. This aligns with the broader migration from PM2 to nodemon process management.

api/src/unraid-api/cli/cli.module.ts (1)

16-67: Dependency injection updated for NodemonService.

The CLI module has been correctly updated to provide NodemonService instead of PM2Service, ensuring all commands receive the new service through dependency injection.

api/src/unraid-api/cli/restart.command.ts (1)

5-35: Restart command successfully migrated to nodemon.

The restart command has been cleanly migrated to use NodemonService with proper environment variable handling (uppercasing LOG_LEVEL). Error handling and logging remain consistent.

api/src/unraid-api/cli/stop.command.ts (1)

3-27: Excellent migration with improved naming.

The stop command has been successfully migrated to NodemonService with a notable improvement: renaming the option from --delete to --force provides better semantic clarity for forcefully stopping the API process. The simplified implementation is cleaner and easier to maintain.

web/src/composables/gql/graphql.ts (4)

562-571: CpuPackages type matches backend schema and Node interface

The new CpuPackages Node type and its fields (power/temp arrays plus totalPower) look consistent with the backend GraphQL snippet and existing Node usage. No issues from the client typing perspective.


1548-1550: PackageVersions nodemon field aligns with pm2→nodemon migration

Adding nodemon?: Maybe<Scalars['String']['output']>; to PackageVersions (and dropping pm2 on the API side) is consistent with the process manager swap. This keeps the web types in sync with the API’s version surface.


2069-2071: New CPU telemetry subscription field is consistent with CpuPackages

systemMetricsCpuTelemetry: CpuPackages cleanly reuses the new type for per-package telemetry and coexists with systemMetricsCpu: CpuUtilization. Typing here looks correct; just ensure any consumers are updated when they start using this subscription.


883-901: Schema verification confirms code alignment – no action needed

The GraphQL schema in api/generated-schema.graphql (lines 1474–1475) explicitly declares both fields as non-nullable:

  • topology: [[[Int!]!]!]!
  • packages: CpuPackages!

The ! suffix in GraphQL enforces non-nullability, meaning the server is required to return these fields. The TypeScript code correctly reflects this by not wrapping them in Maybe<...>. The code is properly aligned with the schema guarantees.

Likely an incorrect or invalid review comment.

api/src/unraid-api/cli/nodemon.service.ts (1)

112-127: Status semantics and stale PID cleanup look good

status correctly reports running/not-running and eagerly cleans up a stale PID file when the process is gone. Returning the boolean while still logging is useful for both CLI and programmatic callers; the implementation here looks solid.

@elibosley elibosley force-pushed the codex/switch-api-process-management-to-nodemon branch from c6cb6d2 to c1f8224 Compare November 21, 2025 21:01
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 (3)
api/src/unraid-api/graph/resolvers/info/versions/versions.resolver.ts (1)

6-43: Nodemon version resolution is correct; consider caching for perf

Using getPackageJson().dependencies?.nodemon inside packages() correctly reports the nodemon version and is safely wrapped in the existing try/catch. The only downside is a synchronous package.json read on each field resolution; if info.versions.packages is queried frequently, you might later introduce a simple in-memory cache for getPackageJson() to avoid repeated disk I/O.

api/src/unraid-api/cli/restart.command.ts (1)

23-36: Consider handling LOG_LEVEL fallback when options.logLevel is absent

env is built as { LOG_LEVEL: options.logLevel?.toUpperCase() } and then passed into this.nodemon.restart({ env }). If run is ever invoked programmatically without CLI option parsing (e.g., restart.run() or restart.run([], {})), options.logLevel will be undefined, so LOG_LEVEL will also be undefined in the env passed to NodemonService.

Depending on how NodemonService.restart uses env, this could either:

  • Silently override a default LOG_LEVEL with undefined, or
  • Cause issues if child process spawning expects string env values.

To make this more robust, consider falling back to the configured default or omitting the key when it’s unset, e.g.:

-            const env = { LOG_LEVEL: options.logLevel?.toUpperCase() };
-            await this.nodemon.restart({ env });
+            const logLevel = options.logLevel ?? LOG_LEVEL.toLowerCase();
+            const env = { LOG_LEVEL: logLevel.toUpperCase() };
+            await this.nodemon.restart({ env });

(or filter out undefined keys inside NodemonService).

api/src/unraid-api/cli/start.command.ts (1)

8-8: Align LOG_LEVEL env handling with a clear default

Similar to RestartCommand, StartCommand builds env as { LOG_LEVEL: options.logLevel?.toUpperCase() } before calling this.nodemon.start(...). While Nest Commander will typically supply a value due to the @Option default, this method can still be called directly in code with an options object that omits logLevel, which would propagate LOG_LEVEL: undefined into the NodemonService layer.

To make behavior explicit and safer, consider normalizing the log level with a fallback to LOG_LEVEL and always passing a concrete string:

-    async run(_: string[], options: LogLevelOptions): Promise<void> {
-        this.logger.info('Starting the Unraid API');
-        await this.nodemon.start({ env: { LOG_LEVEL: options.logLevel?.toUpperCase() } });
-    }
+    async run(_: string[], options: LogLevelOptions): Promise<void> {
+        this.logger.info('Starting the Unraid API');
+        const logLevel = options.logLevel ?? LOG_LEVEL.toLowerCase();
+        await this.nodemon.start({ env: { LOG_LEVEL: logLevel.toUpperCase() } });
+    }

This mirrors the intended default and avoids leaking undefined into the child process environment.

Also applies to: 13-23

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f2ee4ba and c1f8224.

⛔ Files ignored due to path filters (2)
  • api/src/unraid-api/cli/generated/graphql.ts is excluded by !**/generated/**
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (33)
  • api/ecosystem.config.json (0 hunks)
  • api/generated-schema.graphql (1 hunks)
  • api/legacy/generated-schema-legacy.graphql (1 hunks)
  • api/nodemon.json (1 hunks)
  • api/package.json (1 hunks)
  • api/scripts/build.ts (2 hunks)
  • api/src/__test__/core/utils/pm2/dummy-process.js (0 hunks)
  • api/src/__test__/core/utils/pm2/unraid-api-running.integration.test.ts (0 hunks)
  • api/src/__test__/core/utils/process/unraid-api-running.integration.test.ts (1 hunks)
  • api/src/__test__/graphql/resolvers/rclone-api.service.test.ts (1 hunks)
  • api/src/core/log.ts (1 hunks)
  • api/src/core/utils/pm2/unraid-api-running.ts (0 hunks)
  • api/src/core/utils/process/unraid-api-running.ts (1 hunks)
  • api/src/environment.ts (1 hunks)
  • api/src/unraid-api/cli/__test__/report.command.test.ts (3 hunks)
  • api/src/unraid-api/cli/cli-services.module.ts (2 hunks)
  • api/src/unraid-api/cli/cli.module.ts (2 hunks)
  • api/src/unraid-api/cli/logs.command.ts (2 hunks)
  • api/src/unraid-api/cli/nodemon.service.spec.ts (1 hunks)
  • api/src/unraid-api/cli/nodemon.service.ts (1 hunks)
  • api/src/unraid-api/cli/pm2.service.spec.ts (0 hunks)
  • api/src/unraid-api/cli/pm2.service.ts (0 hunks)
  • api/src/unraid-api/cli/report.command.ts (1 hunks)
  • api/src/unraid-api/cli/restart.command.ts (2 hunks)
  • api/src/unraid-api/cli/start.command.ts (1 hunks)
  • api/src/unraid-api/cli/status.command.ts (1 hunks)
  • api/src/unraid-api/cli/stop.command.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/info/versions/versions.model.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/info/versions/versions.resolver.ts (2 hunks)
  • api/src/unraid-api/main.ts (0 hunks)
  • web/composables/gql/graphql.ts (1 hunks)
  • web/src/composables/gql/graphql.ts (5 hunks)
  • web/src/composables/gql/index.ts (1 hunks)
💤 Files with no reviewable changes (7)
  • api/src/unraid-api/main.ts
  • api/src/test/core/utils/pm2/unraid-api-running.integration.test.ts
  • api/src/test/core/utils/pm2/dummy-process.js
  • api/src/core/utils/pm2/unraid-api-running.ts
  • api/ecosystem.config.json
  • api/src/unraid-api/cli/pm2.service.ts
  • api/src/unraid-api/cli/pm2.service.spec.ts
✅ Files skipped from review due to trivial changes (1)
  • web/src/composables/gql/index.ts
🚧 Files skipped from review as they are similar to previous changes (13)
  • api/package.json
  • api/src/unraid-api/cli/cli-services.module.ts
  • api/src/unraid-api/cli/report.command.ts
  • api/scripts/build.ts
  • api/src/unraid-api/graph/resolvers/info/versions/versions.model.ts
  • api/src/unraid-api/cli/test/report.command.test.ts
  • api/src/test/core/utils/process/unraid-api-running.integration.test.ts
  • web/composables/gql/graphql.ts
  • api/nodemon.json
  • api/src/unraid-api/cli/status.command.ts
  • api/src/unraid-api/cli/stop.command.ts
  • api/src/unraid-api/cli/nodemon.service.spec.ts
  • api/src/unraid-api/cli/nodemon.service.ts
🧰 Additional context used
🧠 Learnings (9)
📚 Learning: 2025-02-03T18:57:28.442Z
Learnt from: elibosley
Repo: unraid/api PR: 1101
File: api/src/unraid-api/unraid-file-modifier/modifications/__test__/generic-modification.spec.ts:55-56
Timestamp: 2025-02-03T18:57:28.442Z
Learning: Using console.log is acceptable in test files, especially for debugging test execution. The logger instances in test files are often used as mocks/dependencies for the classes being tested, not for actual logging.

Applied to files:

  • api/src/__test__/graphql/resolvers/rclone-api.service.test.ts
📚 Learning: 2025-03-04T14:55:00.903Z
Learnt from: elibosley
Repo: unraid/api PR: 1151
File: plugin/builder/utils/consts.ts:6-6
Timestamp: 2025-03-04T14:55:00.903Z
Learning: The startingDir constant in plugin/builder/utils/consts.ts is defined using process.cwd(), which can cause issues if directory changes occur after importing this constant. Using __dirname.split('/builder')[0] would make it more reliable by making it relative to the file location rather than the current working directory.

Applied to files:

  • api/src/environment.ts
📚 Learning: 2025-02-05T14:43:48.568Z
Learnt from: elibosley
Repo: unraid/api PR: 1120
File: plugin/package.json:0-0
Timestamp: 2025-02-05T14:43:48.568Z
Learning: In Node.js projects, npm scripts should be organized with clear namespacing (e.g., build:*, docker:*, env:*) and include proper environment validation and error handling. Each script should follow the single responsibility principle.

Applied to files:

  • api/src/environment.ts
📚 Learning: 2025-09-14T14:07:28.265Z
Learnt from: elibosley
Repo: unraid/api PR: 1702
File: web/eslint.config.mjs:106-106
Timestamp: 2025-09-14T14:07:28.265Z
Learning: The unraid/api codebase specifically requires Node 20+ as a minimum version, so modern Node.js features like import.meta.dirname (available since Node v20.11.0) can be used without compatibility fallbacks.

Applied to files:

  • api/src/environment.ts
  • api/src/core/utils/process/unraid-api-running.ts
  • api/src/unraid-api/graph/resolvers/info/versions/versions.resolver.ts
📚 Learning: 2025-03-27T13:34:53.438Z
Learnt from: pujitm
Repo: unraid/api PR: 1252
File: api/src/environment.ts:56-56
Timestamp: 2025-03-27T13:34:53.438Z
Learning: For critical components in the Unraid API, such as retrieving version information from package.json, failing fast (allowing crashes) is preferred over graceful degradation with fallback values.

Applied to files:

  • api/src/core/utils/process/unraid-api-running.ts
📚 Learning: 2024-11-05T14:49:07.308Z
Learnt from: elibosley
Repo: unraid/api PR: 942
File: api/src/unraid-api/auth/api-key.service.ts:62-70
Timestamp: 2024-11-05T14:49:07.308Z
Learning: In `api/src/unraid-api/auth/api-key.service.ts`, when handling read errors in the `findById` method, throw a `GraphQLError` instead of an `InternalServerErrorException`.

Applied to files:

  • api/src/core/utils/process/unraid-api-running.ts
📚 Learning: 2025-01-23T21:26:17.766Z
Learnt from: elibosley
Repo: unraid/api PR: 1063
File: api/src/unraid-api/cli/sso/validate-token.command.ts:76-81
Timestamp: 2025-01-23T21:26:17.766Z
Learning: In the unraid/api codebase, store dispatches using Redux Toolkit's `unwrap()` method already handle errors appropriately and don't require additional try-catch blocks.

Applied to files:

  • api/src/core/utils/process/unraid-api-running.ts
📚 Learning: 2025-02-05T14:43:25.062Z
Learnt from: elibosley
Repo: unraid/api PR: 1120
File: plugin/package.json:1-8
Timestamp: 2025-02-05T14:43:25.062Z
Learning: The repository uses Renovate for automated dependency updates, making strict version pinning in package.json less critical as updates are handled automatically through PRs.

Applied to files:

  • api/src/unraid-api/graph/resolvers/info/versions/versions.resolver.ts
📚 Learning: 2025-02-04T13:48:45.521Z
Learnt from: pujitm
Repo: unraid/api PR: 1104
File: api/src/unraid-api/cli/stop.command.ts:14-18
Timestamp: 2025-02-04T13:48:45.521Z
Learning: The PM2Service's `run` method automatically handles logging when `raw: true` is not set in the context argument. Explicit logging is not needed in such cases.

Applied to files:

  • api/src/unraid-api/cli/logs.command.ts
🧬 Code graph analysis (6)
api/src/core/log.ts (1)
api/src/environment.ts (2)
  • SUPPRESS_LOGS (94-94)
  • LOG_TYPE (88-88)
api/src/core/utils/process/unraid-api-running.ts (2)
packages/unraid-shared/src/util/file.ts (1)
  • fileExists (12-15)
api/src/environment.ts (1)
  • NODEMON_PID_PATH (114-114)
api/src/unraid-api/graph/resolvers/info/versions/versions.resolver.ts (1)
api/src/environment.ts (1)
  • getPackageJson (49-53)
api/src/unraid-api/cli/logs.command.ts (4)
api/src/unraid-api/cli/restart.command.ts (1)
  • Command (21-54)
api/src/unraid-api/cli/start.command.ts (1)
  • Command (11-33)
api/src/unraid-api/cli/status.command.ts (1)
  • Command (5-13)
api/src/unraid-api/cli/stop.command.ts (1)
  • Command (8-28)
web/src/composables/gql/graphql.ts (2)
api/src/unraid-api/cli/generated/graphql.ts (4)
  • CpuPackages (562-571)
  • Node (1385-1387)
  • Scalars (11-75)
  • Maybe (3-3)
web/composables/gql/graphql.ts (3)
  • Node (1357-1359)
  • Scalars (11-75)
  • Maybe (3-3)
api/src/unraid-api/cli/start.command.ts (4)
api/src/unraid-api/cli/logs.command.ts (1)
  • Command (9-25)
api/src/unraid-api/cli/restart.command.ts (2)
  • Command (21-54)
  • LogLevelOptions (9-11)
api/src/unraid-api/cli/status.command.ts (1)
  • Command (5-13)
api/src/unraid-api/cli/stop.command.ts (1)
  • Command (8-28)
🔇 Additional comments (14)
api/src/core/log.ts (1)

20-28: LGTM! Documentation updates align with nodemon migration.

The comment updates correctly reflect the change from PM2-managed stdout to direct file piping. Disabling colorization (colorize: false) remains appropriate to prevent ANSI escape codes from being written to the log file.

api/src/__test__/graphql/resolvers/rclone-api.service.test.ts (1)

54-55: LGTM! Environment mock extended appropriately.

The additions of SUPPRESS_LOGS and LOG_LEVEL to the environment mock are reasonable and align with standard testing practices. These logging configuration values are likely required by the code under test or its dependencies following the nodemon migration.

api/generated-schema.graphql (1)

1676-1677: Schema nodemon version field looks consistent

The new nodemon: String field and its description align with the rest of PackageVersions and with the pm2→nodemon migration; no issues from the schema side.

api/legacy/generated-schema-legacy.graphql (1)

1244-1271: Legacy Versions now exposes nodemon version correctly

Adding nodemon: String to the legacy Versions type keeps it in sync with the new schema and avoids divergence between legacy and current APIs.

web/src/composables/gql/graphql.ts (4)

562-571: CpuPackages client type matches server schema

The new CpuPackages type (Node + power, temp, totalPower) matches the schema and CLI-generated types; no adjustments needed.


883-901: InfoCpu packages/topology fields correctly modeled

Adding packages: CpuPackages and the strongly-typed topology: Array<Array<Array<Scalars['Int']['output']>>> matches the non-null schema definitions and should work as long as the backend resolvers always populate them.

If not already covered, double-check the InfoCpu resolver/model always sets both fields to avoid Cannot return null for non-nullable field errors under load.


1548-1549: PackageVersions nodemon field aligns with backend

Replacing the pm2 field with nodemon?: Maybe<Scalars['String']['output']> and its docstring keeps the frontend typings in sync with the updated PackageVersions schema.


2061-2071: Subscription wiring for systemMetricsCpuTelemetry looks correct

systemMetricsCpuTelemetry: CpuPackages on Subscription mirrors the server-side addition and reuses the new CpuPackages type as expected.

api/src/environment.ts (1)

105-115: Nodemon path and CWD constants now match repo layout

The new NODEMON_PATH, NODEMON_CONFIG_PATH, NODEMON_PID_PATH, and UNRAID_API_CWD values correctly resolve to root-level node_modules/nodemon, api/nodemon.json, the PID file, and the API working directory, fixing the earlier off-by-one issue while remaining overrideable via env vars.

api/src/core/utils/process/unraid-api-running.ts (1)

1-23: Process-running check is robust and race-safe

isUnraidApiRunning correctly guards all I/O and process.kill calls in a try/catch, handles missing/invalid PID values, and safely returns false on any error or race with the pidfile. This gives a clean boolean API for callers without leaking low-level errors.

api/src/unraid-api/cli/logs.command.ts (1)

3-24: Logs command correctly migrated to NodemonService

Injecting NodemonService and delegating run() to this.nodemon.logs(lines) aligns this command with the rest of the nodemon-based CLI lifecycle commands; option parsing semantics are unchanged.

api/src/unraid-api/cli/cli.module.ts (1)

16-71: CLI module wiring for NodemonService is correct

Adding NodemonService to the imports and DEFAULT_PROVIDERS ensures all lifecycle commands (start/stop/status/restart/logs/report) can inject it without additional module changes; the rest of the provider list is untouched.

api/src/unraid-api/cli/restart.command.ts (1)

5-5: Consistent use of LOG_LEVEL for CLI defaults looks good

Importing LOG_LEVEL from @app/environment.js and reusing it as the defaultValue for the --log-level option keeps CLI defaults aligned with the runtime environment and avoids magic strings. Combined with parseLogLevelOption, this keeps validation centralized.

Also applies to: 46-53

api/src/unraid-api/cli/start.command.ts (1)

6-6: Nice reuse of shared log-level parsing and defaults

Using LOG_LEVEL.toLowerCase() as the defaultValue and delegating validation to parseLogLevelOption reused from restart.command.ts keeps CLI behavior consistent across start and restart and avoids duplicating allowed-level logic.

Also applies to: 25-32

@elibosley elibosley force-pushed the codex/switch-api-process-management-to-nodemon branch from c1f8224 to 8f2c826 Compare November 21, 2025 21:53
…demonService

- Updated nodemon.json to remove unnecessary watch entry.
- Adjusted NODEMON_CONFIG_PATH and UNRAID_API_CWD paths for better structure.
- Enhanced error handling in isUnraidApiRunning and start methods of NodemonService to ensure proper logging and resource management.
- Added tests for error scenarios in NodemonService to ensure robustness.
- Introduced UNRAID_API_ROOT to streamline path definitions for nodemon.
- Replaced direct usage of import.meta.dirname with UNRAID_API_ROOT in NODEMON_PATH and UNRAID_API_CWD for improved clarity and maintainability.
- Added dirname import to facilitate the new path structure.
@elibosley elibosley force-pushed the codex/switch-api-process-management-to-nodemon branch from 8f2c826 to b35da13 Compare November 21, 2025 21:53
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: 1

🧹 Nitpick comments (3)
api/src/core/log.ts (1)

20-28: LGTM! Comment updates align with the PM2-to-nodemon migration.

The comment changes appropriately remove PM2-specific references and make the rationale more generic. The logic remains unchanged, and the comments accurately reflect the deployment context where stdout is redirected to log files.

Optional refinement for clarity:

Consider being more explicit that stdout is redirected rather than stating logs are written directly to file. For example:

-// Since process output is piped directly to the log file, we should not colorize stdout
+// Since stdout is redirected to a log file in production, we should not colorize output

and

-            colorize: false, // No colors since logs are written directly to file
+            colorize: false, // No colors since stdout is redirected to file

This would more precisely reflect that pino.destination() writes to stdout by default, with external redirection handling the file output.

api/src/unraid-api/cli/nodemon.service.ts (2)

55-98: Consider handling execa’s promise to avoid unhandled rejections

start() intentionally treats nodemon as a background daemon and never awaits the execa promise, but when nodemon fails very early (spawn error or immediate non‑zero exit), that promise can reject without a .catch, potentially surfacing as an unhandled‑rejection warning even though you also throw a synchronous Error here.

You can keep the fire‑and‑forget behavior but explicitly observe the promise, for example:

-            nodemonProcess = execa(NODEMON_PATH, ['--config', NODEMON_CONFIG_PATH, '--quiet'], {
+            nodemonProcess = execa(NODEMON_PATH, ['--config', NODEMON_CONFIG_PATH, '--quiet'], {
                 cwd: UNRAID_API_CWD,
                 env,
                 detached: true,
                 stdio: ['ignore', 'pipe', 'pipe'],
             });
+
+            // Prevent unhandled rejection noise for this long-running daemon.
+            nodemonProcess.catch(() => {
+                // Intentionally ignored; lifecycle is managed via PID + status().
+            });

This keeps the external behavior the same while hardening against noisy unhandled rejections.


100-118: Stop semantics are acceptable but always clear the PID

stop() is straightforward and robust against missing PID files; note that it removes the PID file even when process.kill throws (e.g., ESRCH). That’s arguably desirable cleanup, but if you ever need to debug “couldn’t signal process X”, consider logging at warn/error as you already do and possibly guarding the PID removal by error type in a follow-up.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c1f8224 and b35da13.

⛔ Files ignored due to path filters (2)
  • api/src/unraid-api/cli/generated/graphql.ts is excluded by !**/generated/**
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (33)
  • api/ecosystem.config.json (0 hunks)
  • api/generated-schema.graphql (1 hunks)
  • api/legacy/generated-schema-legacy.graphql (1 hunks)
  • api/nodemon.json (1 hunks)
  • api/package.json (1 hunks)
  • api/scripts/build.ts (2 hunks)
  • api/src/__test__/core/utils/pm2/dummy-process.js (0 hunks)
  • api/src/__test__/core/utils/pm2/unraid-api-running.integration.test.ts (0 hunks)
  • api/src/__test__/core/utils/process/unraid-api-running.integration.test.ts (1 hunks)
  • api/src/__test__/graphql/resolvers/rclone-api.service.test.ts (1 hunks)
  • api/src/core/log.ts (1 hunks)
  • api/src/core/utils/pm2/unraid-api-running.ts (0 hunks)
  • api/src/core/utils/process/unraid-api-running.ts (1 hunks)
  • api/src/environment.ts (3 hunks)
  • api/src/unraid-api/cli/__test__/report.command.test.ts (3 hunks)
  • api/src/unraid-api/cli/cli-services.module.ts (2 hunks)
  • api/src/unraid-api/cli/cli.module.ts (2 hunks)
  • api/src/unraid-api/cli/logs.command.ts (2 hunks)
  • api/src/unraid-api/cli/nodemon.service.spec.ts (1 hunks)
  • api/src/unraid-api/cli/nodemon.service.ts (1 hunks)
  • api/src/unraid-api/cli/pm2.service.spec.ts (0 hunks)
  • api/src/unraid-api/cli/pm2.service.ts (0 hunks)
  • api/src/unraid-api/cli/report.command.ts (1 hunks)
  • api/src/unraid-api/cli/restart.command.ts (2 hunks)
  • api/src/unraid-api/cli/start.command.ts (1 hunks)
  • api/src/unraid-api/cli/status.command.ts (1 hunks)
  • api/src/unraid-api/cli/stop.command.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/info/versions/versions.model.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/info/versions/versions.resolver.ts (2 hunks)
  • api/src/unraid-api/main.ts (0 hunks)
  • web/composables/gql/graphql.ts (1 hunks)
  • web/src/composables/gql/graphql.ts (5 hunks)
  • web/src/composables/gql/index.ts (1 hunks)
💤 Files with no reviewable changes (7)
  • api/src/unraid-api/cli/pm2.service.spec.ts
  • api/src/test/core/utils/pm2/unraid-api-running.integration.test.ts
  • api/src/unraid-api/main.ts
  • api/src/core/utils/pm2/unraid-api-running.ts
  • api/src/test/core/utils/pm2/dummy-process.js
  • api/src/unraid-api/cli/pm2.service.ts
  • api/ecosystem.config.json
✅ Files skipped from review due to trivial changes (1)
  • web/src/composables/gql/index.ts
🚧 Files skipped from review as they are similar to previous changes (10)
  • api/src/unraid-api/cli/cli-services.module.ts
  • api/src/test/core/utils/process/unraid-api-running.integration.test.ts
  • api/src/unraid-api/cli/nodemon.service.spec.ts
  • api/src/unraid-api/cli/test/report.command.test.ts
  • api/src/unraid-api/cli/report.command.ts
  • api/src/unraid-api/cli/start.command.ts
  • api/src/unraid-api/cli/cli.module.ts
  • api/nodemon.json
  • api/package.json
  • api/generated-schema.graphql
🧰 Additional context used
🧠 Learnings (21)
📓 Common learnings
Learnt from: pujitm
Repo: unraid/api PR: 1367
File: packages/unraid-api-plugin-connect/src/pubsub/user.service.ts:44-52
Timestamp: 2025-04-23T20:19:42.542Z
Learning: The project uses a custom or extended implementation of NestJS ConfigService that includes a `set()` method for runtime configuration mutation, unlike the standard nestjs/config package which only provides getter methods.
📚 Learning: 2025-02-04T13:48:45.521Z
Learnt from: pujitm
Repo: unraid/api PR: 1104
File: api/src/unraid-api/cli/stop.command.ts:14-18
Timestamp: 2025-02-04T13:48:45.521Z
Learning: The PM2Service's `run` method automatically handles logging when `raw: true` is not set in the context argument. Explicit logging is not needed in such cases.

Applied to files:

  • api/src/unraid-api/cli/logs.command.ts
📚 Learning: 2025-03-12T13:48:14.850Z
Learnt from: pujitm
Repo: unraid/api PR: 1211
File: web/composables/gql/gql.ts:17-18
Timestamp: 2025-03-12T13:48:14.850Z
Learning: In the Unraid API project, the duplicate GraphQL query and mutation strings in gql.ts files are intentionally generated by GraphQL CodeGen tool and are necessary for the type system to function properly.

Applied to files:

  • web/composables/gql/graphql.ts
📚 Learning: 2025-09-14T14:07:28.265Z
Learnt from: elibosley
Repo: unraid/api PR: 1702
File: web/eslint.config.mjs:106-106
Timestamp: 2025-09-14T14:07:28.265Z
Learning: The unraid/api codebase specifically requires Node 20+ as a minimum version, so modern Node.js features like import.meta.dirname (available since Node v20.11.0) can be used without compatibility fallbacks.

Applied to files:

  • api/src/unraid-api/graph/resolvers/info/versions/versions.resolver.ts
  • api/src/unraid-api/graph/resolvers/info/versions/versions.model.ts
  • api/src/core/utils/process/unraid-api-running.ts
  • api/src/environment.ts
📚 Learning: 2025-03-27T13:34:53.438Z
Learnt from: pujitm
Repo: unraid/api PR: 1252
File: api/src/environment.ts:56-56
Timestamp: 2025-03-27T13:34:53.438Z
Learning: For critical components in the Unraid API, such as retrieving version information from package.json, failing fast (allowing crashes) is preferred over graceful degradation with fallback values.

Applied to files:

  • api/src/core/utils/process/unraid-api-running.ts
  • api/src/environment.ts
📚 Learning: 2024-11-05T14:49:07.308Z
Learnt from: elibosley
Repo: unraid/api PR: 942
File: api/src/unraid-api/auth/api-key.service.ts:62-70
Timestamp: 2024-11-05T14:49:07.308Z
Learning: In `api/src/unraid-api/auth/api-key.service.ts`, when handling read errors in the `findById` method, throw a `GraphQLError` instead of an `InternalServerErrorException`.

Applied to files:

  • api/src/core/utils/process/unraid-api-running.ts
  • api/src/unraid-api/cli/nodemon.service.ts
📚 Learning: 2025-01-23T21:26:17.766Z
Learnt from: elibosley
Repo: unraid/api PR: 1063
File: api/src/unraid-api/cli/sso/validate-token.command.ts:76-81
Timestamp: 2025-01-23T21:26:17.766Z
Learning: In the unraid/api codebase, store dispatches using Redux Toolkit's `unwrap()` method already handle errors appropriately and don't require additional try-catch blocks.

Applied to files:

  • api/src/core/utils/process/unraid-api-running.ts
📚 Learning: 2025-02-03T18:57:28.442Z
Learnt from: elibosley
Repo: unraid/api PR: 1101
File: api/src/unraid-api/unraid-file-modifier/modifications/__test__/generic-modification.spec.ts:55-56
Timestamp: 2025-02-03T18:57:28.442Z
Learning: Using console.log is acceptable in test files, especially for debugging test execution. The logger instances in test files are often used as mocks/dependencies for the classes being tested, not for actual logging.

Applied to files:

  • api/src/__test__/graphql/resolvers/rclone-api.service.test.ts
📚 Learning: 2025-02-06T17:25:45.397Z
Learnt from: mdatelle
Repo: unraid/api PR: 1122
File: web/package.json:16-16
Timestamp: 2025-02-06T17:25:45.397Z
Learning: The build script in web/package.json should include type-check command (`npm run type-check`) even when NODE_ENV is production, as it provides value for local builds by catching type errors before pushing to CI/CD.

Applied to files:

  • api/scripts/build.ts
  • api/src/unraid-api/cli/nodemon.service.ts
📚 Learning: 2025-03-26T15:18:27.452Z
Learnt from: pujitm
Repo: unraid/api PR: 1252
File: plugin/docker-compose.yml:15-15
Timestamp: 2025-03-26T15:18:27.452Z
Learning: The files in the `api/deploy` directory (including `packed-pnpm-store.txz`) are gitignored build artifacts that are generated when the API is built. Building the API is a prerequisite before using the plugin builder container, as it needs access to these artifacts.

Applied to files:

  • api/scripts/build.ts
📚 Learning: 2025-02-04T16:42:21.782Z
Learnt from: elibosley
Repo: unraid/api PR: 1105
File: api/scripts/build.mjs:0-0
Timestamp: 2025-02-04T16:42:21.782Z
Learning: In Node.js build scripts, avoid manually copying node_modules as a cache layer. Instead, rely on npm's built-in caching mechanism and use direct `npm install` commands, as this ensures dependency consistency and proper version resolution while still maintaining good performance through npm's cache.

Applied to files:

  • api/scripts/build.ts
📚 Learning: 2025-03-04T14:55:00.903Z
Learnt from: elibosley
Repo: unraid/api PR: 1151
File: plugin/builder/utils/consts.ts:6-6
Timestamp: 2025-03-04T14:55:00.903Z
Learning: The startingDir constant in plugin/builder/utils/consts.ts is defined using process.cwd(), which can cause issues if directory changes occur after importing this constant. Using __dirname.split('/builder')[0] would make it more reliable by making it relative to the file location rather than the current working directory.

Applied to files:

  • api/src/environment.ts
📚 Learning: 2025-02-05T14:43:48.568Z
Learnt from: elibosley
Repo: unraid/api PR: 1120
File: plugin/package.json:0-0
Timestamp: 2025-02-05T14:43:48.568Z
Learning: In Node.js projects, npm scripts should be organized with clear namespacing (e.g., build:*, docker:*, env:*) and include proper environment validation and error handling. Each script should follow the single responsibility principle.

Applied to files:

  • api/src/environment.ts
  • api/src/unraid-api/cli/nodemon.service.ts
📚 Learning: 2025-04-23T20:19:42.542Z
Learnt from: pujitm
Repo: unraid/api PR: 1367
File: packages/unraid-api-plugin-connect/src/pubsub/user.service.ts:44-52
Timestamp: 2025-04-23T20:19:42.542Z
Learning: The project uses a custom or extended implementation of NestJS ConfigService that includes a `set()` method for runtime configuration mutation, unlike the standard nestjs/config package which only provides getter methods.

Applied to files:

  • api/src/environment.ts
📚 Learning: 2025-05-23T21:59:29.632Z
Learnt from: elibosley
Repo: unraid/api PR: 1408
File: web/components/ApiKey/PermissionCounter.vue:6-6
Timestamp: 2025-05-23T21:59:29.632Z
Learning: This codebase uses ESM (ECMAScript Modules) and requires .js extensions in import statements, even when importing from TypeScript files, as the imports refer to the compiled JavaScript output.

Applied to files:

  • api/src/environment.ts
📚 Learning: 2025-04-23T20:22:36.001Z
Learnt from: pujitm
Repo: unraid/api PR: 1367
File: api/src/unraid-api/app/pubsub.module.ts:24-28
Timestamp: 2025-04-23T20:22:36.001Z
Learning: In the Unraid API project, string literals are intentionally used for dependency injection tokens instead of Symbols to enable "collision" behavior across modules that don't directly import from each other. This is a temporary approach during refactoring until a shared library for constants is implemented.

Applied to files:

  • api/src/environment.ts
📚 Learning: 2025-09-02T19:35:14.427Z
Learnt from: elibosley
Repo: unraid/api PR: 1639
File: web/components/standalone-mount.ts:38-54
Timestamp: 2025-09-02T19:35:14.427Z
Learning: In the unraid/api project, exposing Apollo client and GraphQL utilities (apolloClient, gql, graphqlParse) on the global window object is intentional to allow developers to interact with GraphQL from the browser console without needing to be inside Vue components. Developer experience is prioritized over minimizing global exposure in this context.

Applied to files:

  • api/src/environment.ts
📚 Learning: 2025-04-21T18:25:16.491Z
Learnt from: pujitm
Repo: unraid/api PR: 1352
File: api/src/unraid-api/cli/dependency.service.ts:114-117
Timestamp: 2025-04-21T18:25:16.491Z
Learning: Error masking through try/catch blocks is not desirable for the `npmInstall` method in `DependencyService` as errors should propagate to the caller.

Applied to files:

  • api/src/unraid-api/cli/nodemon.service.ts
📚 Learning: 2025-03-07T19:29:12.540Z
Learnt from: pujitm
Repo: unraid/api PR: 1219
File: api/src/unraid-api/main.ts:18-25
Timestamp: 2025-03-07T19:29:12.540Z
Learning: When handling type mismatches between dependencies in TypeScript (such as between NestJS and Fastify), prefer using `ts-expect-error` with a detailed explanation comment instead of `as any` type assertions. This better documents the reason for the type bypass and makes the issue more visible for future maintenance.

Applied to files:

  • api/src/unraid-api/cli/nodemon.service.ts
📚 Learning: 2025-04-21T18:25:16.491Z
Learnt from: pujitm
Repo: unraid/api PR: 1352
File: api/src/unraid-api/cli/dependency.service.ts:114-117
Timestamp: 2025-04-21T18:25:16.491Z
Learning: Methods in `DependencyService` like `npmInstall` and `rebuildVendorArchive` intentionally propagate errors from execa calls upward rather than handling them internally, allowing callers to implement appropriate error handling. This follows the pattern documented in the `rebuildVendorArchive` method's docstring.

Applied to files:

  • api/src/unraid-api/cli/nodemon.service.ts
📚 Learning: 2025-03-13T16:17:55.820Z
Learnt from: elibosley
Repo: unraid/api PR: 1211
File: api/src/unraid-api/graph/connect/connect-settings.service.ts:48-53
Timestamp: 2025-03-13T16:17:55.820Z
Learning: In NestJS services, dynamic imports should be wrapped in try/catch blocks with proper error logging and fallback handling to prevent unhandled rejections from crashing the application.

Applied to files:

  • api/src/unraid-api/cli/nodemon.service.ts
🧬 Code graph analysis (9)
api/src/unraid-api/cli/logs.command.ts (4)
api/src/unraid-api/cli/restart.command.ts (1)
  • Command (21-54)
api/src/unraid-api/cli/start.command.ts (1)
  • Command (11-33)
api/src/unraid-api/cli/status.command.ts (1)
  • Command (5-13)
api/src/unraid-api/cli/stop.command.ts (1)
  • Command (8-28)
web/composables/gql/graphql.ts (1)
web/src/composables/gql/graphql.ts (2)
  • Maybe (3-3)
  • Scalars (11-75)
api/src/unraid-api/graph/resolvers/info/versions/versions.resolver.ts (1)
api/src/environment.ts (1)
  • getPackageJson (49-53)
api/src/unraid-api/cli/status.command.ts (4)
api/src/unraid-api/cli/logs.command.ts (1)
  • Command (9-25)
api/src/unraid-api/cli/restart.command.ts (1)
  • Command (21-54)
api/src/unraid-api/cli/start.command.ts (1)
  • Command (11-33)
api/src/unraid-api/cli/stop.command.ts (1)
  • Command (8-28)
api/src/core/log.ts (1)
api/src/environment.ts (2)
  • SUPPRESS_LOGS (95-95)
  • LOG_TYPE (89-89)
api/src/core/utils/process/unraid-api-running.ts (2)
packages/unraid-shared/src/util/file.ts (1)
  • fileExists (12-15)
api/src/environment.ts (1)
  • NODEMON_PID_PATH (108-108)
web/src/composables/gql/graphql.ts (1)
api/src/unraid-api/cli/generated/graphql.ts (3)
  • CpuPackages (562-571)
  • Node (1385-1387)
  • Scalars (11-75)
api/src/unraid-api/cli/stop.command.ts (4)
api/src/unraid-api/cli/logs.command.ts (1)
  • Command (9-25)
api/src/unraid-api/cli/restart.command.ts (1)
  • Command (21-54)
api/src/unraid-api/cli/start.command.ts (1)
  • Command (11-33)
api/src/unraid-api/cli/status.command.ts (1)
  • Command (5-13)
api/src/unraid-api/cli/nodemon.service.ts (3)
api/src/environment.ts (6)
  • PATHS_LOGS_DIR (102-103)
  • NODEMON_PID_PATH (108-108)
  • PATHS_LOGS_FILE (104-104)
  • NODEMON_PATH (106-106)
  • NODEMON_CONFIG_PATH (107-107)
  • UNRAID_API_CWD (109-109)
packages/unraid-shared/src/util/file.ts (1)
  • fileExists (12-15)
api/src/unraid-api/cli/log.service.ts (1)
  • error (65-69)
🔇 Additional comments (20)
api/scripts/build.ts (1)

97-97: LGTM! Nodemon config copy aligns with PM2 migration.

The change from copying ecosystem.config.json to nodemon.json correctly reflects the migration from PM2 to nodemon process management, ensuring the nodemon configuration is packaged in the release artifacts.

api/legacy/generated-schema-legacy.graphql (1)

1260-1260: LGTM! GraphQL schema updated for nodemon migration.

The field change from pm2: String to nodemon: String in the Versions type correctly reflects the transition from PM2 to nodemon process management in the GraphQL API surface.

api/src/unraid-api/graph/resolvers/info/versions/versions.model.ts (1)

28-29: LGTM! Model definition updated consistently with schema.

The field change from pm2?: string to nodemon?: string with the updated description properly reflects the nodemon migration and maintains consistency with the GraphQL schema changes.

web/composables/gql/graphql.ts (1)

1526-1527: LGTM! Generated types updated from GraphQL schema.

The PackageVersions type change from pm2 to nodemon is auto-generated by GraphQL CodeGen and correctly reflects the updated schema. As learnings indicate, the generated code structure is intentional for proper type system function.

api/src/environment.ts (1)

5-5: LGTM! Clean path derivation using UNRAID_API_ROOT.

The introduction of UNRAID_API_ROOT as a base for nodemon-related paths is a solid improvement over the previous approach. Using dirname(getPackageJsonPath()) provides a reliable anchor point for:

  • NODEMON_CONFIG_PATHapi/nodemon.json
  • NODEMON_PATHapi/node_modules/nodemon/bin/nodemon.js (valid in pnpm workspaces)
  • UNRAID_API_CWDapi/ (correct working directory)

This approach is more maintainable and addresses the path construction issues noted in previous reviews.

Also applies to: 68-68, 106-109

api/src/unraid-api/graph/resolvers/info/versions/versions.resolver.ts (1)

6-6: Clarify nodemon version format - dependency declaration vs installed version.

The code now reads the nodemon version from package.json dependencies using getPackageJson().dependencies?.nodemon. This will return the dependency declaration (e.g., "^3.0.0") rather than the actual installed version.

Is it acceptable to show the semver range specification, or should this display the resolved installed version instead? If the latter, consider using await versions() from systeminformation (which is already imported) or reading from node_modules/nodemon/package.json.

Current behavior: Shows "^3.0.0" (declared dependency)
Alternative: Show "3.1.4" (installed version)

Also applies to: 38-38

api/src/__test__/graphql/resolvers/rclone-api.service.test.ts (1)

54-55: LGTM! Test mock extended with logging controls.

Adding SUPPRESS_LOGS and LOG_LEVEL to the environment mock provides proper test-level control over logging behavior, aligning with the logging controls used in the nodemon-based process management workflow.

api/src/core/utils/process/unraid-api-running.ts (1)

1-23: LGTM! Robust nodemon process check with proper error handling.

The implementation correctly verifies if the Unraid API is running under nodemon by:

  1. Checking PID file existence at NODEMON_PID_PATH
  2. Reading and parsing the PID
  3. Verifying the process is alive using process.kill(pid, 0)

The comprehensive try-catch wrapper properly handles all error cases (missing file, I/O errors, invalid PID, dead process) by returning false, addressing the concerns raised in previous reviews. This provides a clean boolean interface without error leakage.

web/src/composables/gql/graphql.ts (4)

562-571: CpuPackages type matches backend schema

The CpuPackages node shape (id/power/temp/totalPower) aligns with the CLI-generated GraphQL types and looks correct for client usage.


883-901: InfoCpu extensions are consistent and well-documented

Adding packages: CpuPackages and the topology triple-nested array with an example docstring makes the per-package CPU view clear and type-safe.


1548-1549: nodemon version field fits PackageVersions model

Introducing the optional nodemon version alongside existing package fields cleanly reflects the runtime process manager swap.


2070-2070: CPU telemetry subscription wiring looks correct

systemMetricsCpuTelemetry: CpuPackages matches the new CpuPackages node and should integrate cleanly with telemetry consumers.

api/src/unraid-api/cli/nodemon.service.ts (4)

34-44: PID file handling helper is reasonable

ensureNodemonDependencies + getStoredPid/parseInt give a clear, small surface for PID management; letting mkdir errors propagate is appropriate so callers can abort early.


46-53: Process liveness check is simple and idiomatic

Using process.kill(pid, 0) with a try/catch to probe liveness is a standard, low-overhead approach here.


125-140: Status correctly reconciles stale PID files

status() returning a boolean and cleaning up stale PID files when the process is no longer running provides a good single source of truth for higher-level commands.


142-160: Logs helper behavior is caller-friendly

logs() tails via execa('tail', ...), logs the content, and returns it, while gracefully handling file-missing/errors and emitting clear messages. Returning an empty string on failure is a reasonable, non-throwing contract for CLI callers.

api/src/unraid-api/cli/logs.command.ts (1)

3-24: LogsCommand–NodemonService integration looks clean

Constructor injection of NodemonService and delegating logs(lines) after simple, defensive parsing of the --lines option is straightforward and keeps CLI logic thin.

api/src/unraid-api/cli/status.command.ts (1)

3-12: StatusCommand correctly delegates to NodemonService

Swapping to NodemonService and simply awaiting nodemon.status() keeps the command minimal and aligns with the new process-manager abstraction.

api/src/unraid-api/cli/restart.command.ts (1)

5-53: Restart flow via NodemonService is consistent and robust

Delegating restarts to nodemon.restart({ env }) with normalized LOG_LEVEL, plus structured try/catch that logs a clear message and exits with code 1 on failure, gives a clean and predictable restart UX in line with the start command.

api/src/unraid-api/cli/stop.command.ts (1)

3-27: StopCommand force option and NodemonService wiring make intent clear

Injecting NodemonService and exposing a -f, --force flag that maps directly to { force } for nodemon.stop makes the stop behavior explicit (SIGTERM vs SIGKILL) while keeping the command logic minimal.

import { $, cd } from 'zx';

import { getDeploymentVersion } from './get-deployment-version.js';
import { getDeploymentVersion } from '@app/../scripts/get-deployment-version.js';
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify the import path change for getDeploymentVersion.

The import path changed from './get-deployment-version.js' (resolving to api/scripts/get-deployment-version.js) to '@app/../scripts/get-deployment-version.js' (resolving to scripts/get-deployment-version.js at repo root). This suggests the file was moved from the api/scripts directory to a root-level scripts directory.

Run the following script to verify the file exists at the expected location:


🏁 Script executed:

#!/bin/bash
# Description: Verify get-deployment-version.js exists at the new location

echo "Checking for get-deployment-version.js..."
if [ -f "scripts/get-deployment-version.js" ]; then
    echo "✓ Found at scripts/get-deployment-version.js"
    echo "File contents preview:"
    head -10 scripts/get-deployment-version.js
elif [ -f "api/scripts/get-deployment-version.js" ]; then
    echo "⚠ File still exists at old location: api/scripts/get-deployment-version.js"
    echo "The import path may be incorrect"
else
    echo "✗ File not found at either location"
fi

Length of output: 77


The file doesn't exist at either location. Let me search the entire repository to determine where this file actually is:


🏁 Script executed:

#!/bin/bash
# Search for any files with get-deployment-version in the name

echo "Searching for get-deployment-version files in repo..."
fd "get-deployment-version" --type f

echo -e "\n---"
echo "Checking if file exists anywhere with different extension..."
fd "get-deployment-version" --type f -e ts -e js -e mjs

echo -e "\n---"
echo "Searching for references to getDeploymentVersion..."
rg "getDeploymentVersion" -n --type ts --type js 2>/dev/null | head -20

Length of output: 632


Let me verify the module alias configuration to understand how @app resolves:


🏁 Script executed:

#!/bin/bash
# Find tsconfig or path alias configuration

echo "Looking for tsconfig.json files..."
fd "tsconfig" --type f

echo -e "\n---"
echo "Checking for path alias configuration in tsconfig..."
rg '"@app"' --type json -A2 -B2

echo -e "\n---"
echo "Checking import in build.ts context..."
rg -n -B2 -A5 "import.*getDeploymentVersion" git/api/scripts/build.ts

Length of output: 885


Let me check the specific tsconfig.json in the api directory where build.ts is located:


🏁 Script executed:

#!/bin/bash
# Check the api tsconfig.json for @app alias

echo "Contents of api/tsconfig.json:"
cat git/api/tsconfig.json

echo -e "\n---"
echo "Checking for package.json in api directory:"
cat git/api/package.json 2>/dev/null | head -40

echo -e "\n---"
echo "Double-checking - what is the correct relative import from build.ts to get-deployment-version.ts?"
echo "build.ts location: api/scripts/build.ts"
echo "get-deployment-version.ts location: api/scripts/get-deployment-version.ts"
echo "Correct import should be: './get-deployment-version.js' or './get-deployment-version.ts'"

Length of output: 4417


Fix broken import path and extension in build.ts line 10.

The import path is incorrect on multiple levels:

  • @app/../scripts/get-deployment-version.js resolves to ./scripts/get-deployment-version.js (repo root) via the @app alias mapping ("@app/*": ["./src/*"] in api/tsconfig.json)
  • The actual file is located at api/scripts/get-deployment-version.ts (same directory as build.ts)
  • The file does not exist at the resolved path

Change line 10 to:

import { getDeploymentVersion } from './get-deployment-version.js';
🤖 Prompt for AI Agents
In api/scripts/build.ts around line 10, the import path uses the @app alias and
points to @app/../scripts/get-deployment-version.js which resolves incorrectly
to the repo root and the target file doesn't exist there; update the import to
reference the local sibling module by changing it to import from
'./get-deployment-version.js' so it correctly loads
api/scripts/get-deployment-version.ts (compiled .js at runtime).

… handling

- Introduced a new test file to validate nodemon path configurations, ensuring they anchor to the package root by default.
- Enhanced the NodemonService to throw an error when nodemon exits immediately after starting, improving robustness.
- Added tests to cover scenarios where nodemon fails to start, ensuring proper logging and resource cleanup.
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 (1)
api/src/__test__/environment.nodemon-paths.test.ts (1)

1-28: Solid test for nodemon path derivation; consider adding a second case for explicit CWD.

This test is well-structured: it safely snapshots/restores UNRAID_API_CWD, resets modules before each run so @app/environment.js re-evaluates with a clean env, and asserts the nodemon paths are anchored to UNRAID_API_ROOT as expected. No functional issues spotted.

As a small enhancement, you might add a second test that sets process.env.UNRAID_API_CWD before importing @app/environment.js and asserts that UNRAID_API_CWD reflects the override while NODEMON_CONFIG_PATH and NODEMON_PATH still anchor to UNRAID_API_ROOT. That would lock in both default and overridden behavior for the new env wiring.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b35da13 and d4f90d6.

📒 Files selected for processing (3)
  • api/src/__test__/environment.nodemon-paths.test.ts (1 hunks)
  • api/src/unraid-api/cli/nodemon.service.spec.ts (1 hunks)
  • api/src/unraid-api/cli/nodemon.service.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • api/src/unraid-api/cli/nodemon.service.spec.ts
  • api/src/unraid-api/cli/nodemon.service.ts
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: pujitm
Repo: unraid/api PR: 1367
File: packages/unraid-api-plugin-connect/src/pubsub/user.service.ts:44-52
Timestamp: 2025-04-23T20:19:42.542Z
Learning: The project uses a custom or extended implementation of NestJS ConfigService that includes a `set()` method for runtime configuration mutation, unlike the standard nestjs/config package which only provides getter methods.
🧬 Code graph analysis (1)
api/src/__test__/environment.nodemon-paths.test.ts (1)
api/src/environment.ts (5)
  • environment (73-75)
  • UNRAID_API_CWD (109-109)
  • UNRAID_API_ROOT (68-68)
  • NODEMON_CONFIG_PATH (107-107)
  • NODEMON_PATH (106-106)

- Updated the return type of killSpy in nodemon.service.spec.ts to directly return a boolean instead of casting it, improving code clarity and maintainability.
- Implemented stopPm2IfRunning method to stop any running pm2-managed instances of unraid-api before starting nodemon.
- Added findMatchingNodemonPids method to identify existing nodemon processes, improving resource management.
- Updated start method to handle scenarios where a stored pid is running or dead, ensuring proper cleanup and logging.
- Introduced new unit tests to validate the new functionality and ensure robustness in process handling.
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 (3)
api/src/unraid-api/cli/nodemon.service.ts (3)

4-5: Remove unused imports flagged by static analysis

homedir (Line 4) and join (Line 5) are imported but never used. Please drop them to keep the module clean and satisfy the CodeQL notice.

-import { homedir } from 'node:os';
-import { dirname, join } from 'node:path';
+import { dirname } from 'node:path';

35-38: Optionally add explicit return type to clarify intent

ensureNodemonDependencies currently relies on inference. For a public-ish service API, giving it an explicit Promise<void> return type makes the contract clearer and consistent with other async methods:

-    async ensureNodemonDependencies() {
+    async ensureNodemonDependencies(): Promise<void> {
         await mkdir(PATHS_LOGS_DIR, { recursive: true });
         await mkdir(dirname(NODEMON_PID_PATH), { recursive: true });
     }

140-182: Avoid double‑closing logStream and verify long‑running log behavior

Two related points in start:

  1. Double logStream.close() on error paths

logStream.close() is called inside the if (!nodemonProcess.pid) and if (!stillRunning) branches (Lines 160 and 172) and then again in the catch block (Line 179). This is redundant and can lead to awkward double‑close behavior.

You can rely on the catch block to close the stream and remove the inner closes:

-            if (!nodemonProcess.pid) {
-                logStream.close();
-                throw new Error('Failed to start nodemon: process spawned but no PID was assigned');
-            }
+            if (!nodemonProcess.pid) {
+                throw new Error('Failed to start nodemon: process spawned but no PID was assigned');
+            }
@@
-            if (!stillRunning) {
-                const recentLogs = await this.logs(50);
-                await rm(NODEMON_PID_PATH, { force: true });
-                logStream.close();
-                const logMessage = recentLogs ? ` Recent logs:\n${recentLogs}` : '';
-                throw new Error(`Nodemon exited immediately after start.${logMessage}`);
-            }
+            if (!stillRunning) {
+                const recentLogs = await this.logs(50);
+                await rm(NODEMON_PID_PATH, { force: true });
+                const logMessage = recentLogs ? ` Recent logs:\n${recentLogs}` : '';
+                throw new Error(`Nodemon exited immediately after start.${logMessage}`);
+            }
  1. Confirm that logs continue after the CLI process exits

Right now, nodemon’s stdout/stderr are piped into a createWriteStream(PATHS_LOGS_FILE) owned by this process. If the CLI process exits shortly after start returns (which is typical for a detached daemon pattern), any further logging from nodemon will no longer go through this stream.

If PATHS_LOGS_FILE is intended to capture long‑running API logs via this pipeline, consider instead wiring the log file directly via stdio FDs in the execa options so the child owns its log descriptors even after the CLI exits. For example (sketch only, adjust to your conventions):

// Before spawning:
const outFd = fs.openSync(PATHS_LOGS_FILE, 'a');
const errFd = fs.openSync(PATHS_LOGS_FILE, 'a');

const nodemonProcess = execa(NODEMON_PATH, ['--config', NODEMON_CONFIG_PATH, '--quiet'], {
  cwd: UNRAID_API_CWD,
  env,
  detached: true,
  stdio: ['ignore', outFd, errFd],
});

Then you can drop the logStream and explicit piping altogether.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 33e88bc and 1d9c76f.

📒 Files selected for processing (2)
  • api/src/unraid-api/cli/nodemon.service.spec.ts (1 hunks)
  • api/src/unraid-api/cli/nodemon.service.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • api/src/unraid-api/cli/nodemon.service.spec.ts
🧰 Additional context used
🧠 Learnings (8)
📓 Common learnings
Learnt from: pujitm
Repo: unraid/api PR: 1367
File: packages/unraid-api-plugin-connect/src/pubsub/user.service.ts:44-52
Timestamp: 2025-04-23T20:19:42.542Z
Learning: The project uses a custom or extended implementation of NestJS ConfigService that includes a `set()` method for runtime configuration mutation, unlike the standard nestjs/config package which only provides getter methods.
📚 Learning: 2025-04-21T18:25:16.491Z
Learnt from: pujitm
Repo: unraid/api PR: 1352
File: api/src/unraid-api/cli/dependency.service.ts:114-117
Timestamp: 2025-04-21T18:25:16.491Z
Learning: Error masking through try/catch blocks is not desirable for the `npmInstall` method in `DependencyService` as errors should propagate to the caller.

Applied to files:

  • api/src/unraid-api/cli/nodemon.service.ts
📚 Learning: 2025-03-07T19:29:12.540Z
Learnt from: pujitm
Repo: unraid/api PR: 1219
File: api/src/unraid-api/main.ts:18-25
Timestamp: 2025-03-07T19:29:12.540Z
Learning: When handling type mismatches between dependencies in TypeScript (such as between NestJS and Fastify), prefer using `ts-expect-error` with a detailed explanation comment instead of `as any` type assertions. This better documents the reason for the type bypass and makes the issue more visible for future maintenance.

Applied to files:

  • api/src/unraid-api/cli/nodemon.service.ts
📚 Learning: 2025-04-21T18:25:16.491Z
Learnt from: pujitm
Repo: unraid/api PR: 1352
File: api/src/unraid-api/cli/dependency.service.ts:114-117
Timestamp: 2025-04-21T18:25:16.491Z
Learning: Methods in `DependencyService` like `npmInstall` and `rebuildVendorArchive` intentionally propagate errors from execa calls upward rather than handling them internally, allowing callers to implement appropriate error handling. This follows the pattern documented in the `rebuildVendorArchive` method's docstring.

Applied to files:

  • api/src/unraid-api/cli/nodemon.service.ts
📚 Learning: 2025-03-13T16:17:55.820Z
Learnt from: elibosley
Repo: unraid/api PR: 1211
File: api/src/unraid-api/graph/connect/connect-settings.service.ts:48-53
Timestamp: 2025-03-13T16:17:55.820Z
Learning: In NestJS services, dynamic imports should be wrapped in try/catch blocks with proper error logging and fallback handling to prevent unhandled rejections from crashing the application.

Applied to files:

  • api/src/unraid-api/cli/nodemon.service.ts
📚 Learning: 2024-11-05T14:49:07.308Z
Learnt from: elibosley
Repo: unraid/api PR: 942
File: api/src/unraid-api/auth/api-key.service.ts:62-70
Timestamp: 2024-11-05T14:49:07.308Z
Learning: In `api/src/unraid-api/auth/api-key.service.ts`, when handling read errors in the `findById` method, throw a `GraphQLError` instead of an `InternalServerErrorException`.

Applied to files:

  • api/src/unraid-api/cli/nodemon.service.ts
📚 Learning: 2025-02-06T17:25:45.397Z
Learnt from: mdatelle
Repo: unraid/api PR: 1122
File: web/package.json:16-16
Timestamp: 2025-02-06T17:25:45.397Z
Learning: The build script in web/package.json should include type-check command (`npm run type-check`) even when NODE_ENV is production, as it provides value for local builds by catching type errors before pushing to CI/CD.

Applied to files:

  • api/src/unraid-api/cli/nodemon.service.ts
📚 Learning: 2025-02-05T14:43:48.568Z
Learnt from: elibosley
Repo: unraid/api PR: 1120
File: plugin/package.json:0-0
Timestamp: 2025-02-05T14:43:48.568Z
Learning: In Node.js projects, npm scripts should be organized with clear namespacing (e.g., build:*, docker:*, env:*) and include proper environment validation and error handling. Each script should follow the single responsibility principle.

Applied to files:

  • api/src/unraid-api/cli/nodemon.service.ts
🧬 Code graph analysis (1)
api/src/unraid-api/cli/nodemon.service.ts (3)
api/src/environment.ts (6)
  • PATHS_LOGS_DIR (102-103)
  • NODEMON_PID_PATH (108-108)
  • NODEMON_CONFIG_PATH (107-107)
  • PATHS_LOGS_FILE (104-104)
  • NODEMON_PATH (106-106)
  • UNRAID_API_CWD (109-109)
packages/unraid-shared/src/util/file.ts (1)
  • fileExists (12-15)
api/src/unraid-api/cli/log.service.ts (1)
  • error (65-69)
🪛 GitHub Check: CodeQL
api/src/unraid-api/cli/nodemon.service.ts

[notice] 4-4: Unused variable, import, function or class
Unused import homedir.


[notice] 5-5: Unused variable, import, function or class
Unused import join.

🔇 Additional comments (2)
api/src/unraid-api/cli/nodemon.service.ts (2)

70-84: PID file/liveness helpers look solid

getStoredPid and isPidRunning are straightforward and robust (NaN‑safe parsing and kill(pid, 0) check), which should work well with the rest of the lifecycle methods.


227-245: Nice, logs() now handles missing file/errors gracefully

Wrapping the tail call in try/catch and distinguishing ENOENT from other failures yields much clearer diagnostics while returning a safe fallback string for callers.

- Implemented findDirectMainPids and terminatePids methods to identify and terminate existing unraid-api processes before starting nodemon.
- Enhanced the start method to include checks for running processes, ensuring proper cleanup and logging.
- Updated unit tests to validate the new process management functionality, improving overall robustness.
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 (1)
api/src/unraid-api/cli/nodemon.service.spec.ts (1)

63-64: Simplify mock return values.

The explicit type casting is unnecessary since mockResolvedValue(undefined) correctly types to Promise<void>.

Apply this diff to simplify:

-        mockWriteFile.mockResolvedValue(undefined as unknown as void);
-        mockRm.mockResolvedValue(undefined as unknown as void);
+        mockWriteFile.mockResolvedValue(undefined);
+        mockRm.mockResolvedValue(undefined);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1d9c76f and 9253250.

📒 Files selected for processing (2)
  • api/src/unraid-api/cli/nodemon.service.spec.ts (1 hunks)
  • api/src/unraid-api/cli/nodemon.service.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • api/src/unraid-api/cli/nodemon.service.ts
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: pujitm
Repo: unraid/api PR: 1367
File: packages/unraid-api-plugin-connect/src/pubsub/user.service.ts:44-52
Timestamp: 2025-04-23T20:19:42.542Z
Learning: The project uses a custom or extended implementation of NestJS ConfigService that includes a `set()` method for runtime configuration mutation, unlike the standard nestjs/config package which only provides getter methods.
🧬 Code graph analysis (1)
api/src/unraid-api/cli/nodemon.service.spec.ts (1)
packages/unraid-shared/src/util/file.ts (1)
  • fileExists (12-15)
🔇 Additional comments (4)
api/src/unraid-api/cli/nodemon.service.spec.ts (4)

18-27: Environment mock is now complete.

The addition of SUPPRESS_LOGS resolves the previous pipeline failure. The mock now correctly mirrors all necessary exports from environment.ts.


91-312: Comprehensive start method test coverage.

The test suite thoroughly covers the start method's behavior across multiple scenarios:

  • ✅ Successful start with proper setup and PID file management
  • ✅ Error handling with appropriate cleanup (closing streams, removing stale files)
  • ✅ Edge cases (already running, stale PID files, immediate exit detection)
  • ✅ Process discovery and adoption
  • ✅ Termination of conflicting direct main.js processes

The tests properly verify that cleanup occurs on failures and that diagnostic information is collected when nodemon exits unexpectedly.


314-362: Well-tested status and logs methods.

The tests for status and logs methods properly verify:

  • Correct status reporting when PID file is absent
  • Successful log retrieval via tail command
  • Graceful error handling for missing log files (ENOENT)
  • Proper error logging for tail command failures

1-363: Excellent test suite with thorough coverage.

This test file demonstrates strong testing practices:

  • ✅ Comprehensive coverage of all public methods
  • ✅ Proper mock setup and isolation via beforeEach
  • ✅ Both success and failure paths tested
  • ✅ Error handling and cleanup verified
  • ✅ Edge cases covered (stale PIDs, already running, immediate exit)
  • ✅ Appropriate assertions for behavior and logging

The test suite provides confidence that NodemonService will handle various runtime scenarios correctly.

…n NodemonService

- Added waitForNodemonExit method to ensure nodemon processes are fully terminated before restarting.
- Updated restart method to call waitForNodemonExit, improving process management during restarts.
- Introduced a new unit test to validate the behavior of the restart method, ensuring proper sequence of stop, wait, and start operations.
@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/PR1798/dynamix.unraid.net.plg

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants